Browse Source

refactor(nc-cli): prettier source code

pull/4237/head
Wing-Kam Wong 2 years ago
parent
commit
9fd51c7792
  1. 34
      packages/nc-cli/src/index.ts
  2. 19
      packages/nc-cli/src/lib/CliMgr.ts
  3. 77
      packages/nc-cli/src/lib/mgr/AppMgr.ts
  4. 41
      packages/nc-cli/src/lib/mgr/Client.ts
  5. 26
      packages/nc-cli/src/lib/mgr/ComponentMgr.ts
  6. 26
      packages/nc-cli/src/lib/mgr/DockerMgr.ts
  7. 23
      packages/nc-cli/src/lib/mgr/InstantMgr.ts
  8. 50
      packages/nc-cli/src/lib/mgr/MigrationMgr.ts
  9. 44
      packages/nc-cli/src/lib/mgr/ModelMgr.ts
  10. 400
      packages/nc-cli/src/lib/mgr/NewMgr.ts
  11. 122
      packages/nc-cli/src/lib/mgr/OldNewMgr.ts
  12. 516
      packages/nc-cli/src/lib/mgr/PermissionsMgr.ts
  13. 537
      packages/nc-cli/src/lib/mgr/PermissionsMgrJs.ts
  14. 77
      packages/nc-cli/src/lib/mgr/SocialMgr.ts
  15. 19
      packages/nc-cli/src/lib/mgr/SocialText.ts
  16. 132
      packages/nc-cli/src/lib/mgr/TryMgr.ts
  17. 77
      packages/nc-cli/src/lib/mgr/XcInstantMgr.ts
  18. 53
      packages/nc-cli/src/lib/prompts/Menu.ts
  19. 20
      packages/nc-cli/src/lib/prompts/RunOrDownload.ts
  20. 23
      packages/nc-cli/src/lib/util/Lang.ts
  21. 347
      packages/nc-cli/src/lib/util/Locales.ts
  22. 301
      packages/nc-cli/src/lib/util/Util.ts
  23. 5
      packages/nc-cli/src/lib/util/config.ts

34
packages/nc-cli/src/index.ts

@ -6,48 +6,54 @@ import Util from './lib/util/Util';
import updateNotifier from 'update-notifier'; import updateNotifier from 'update-notifier';
// tslint:disable-next-line:no-var-requires // tslint:disable-next-line:no-var-requires
const pkg = require('../package.json'); const pkg = require('../package.json');
import yargs from 'yargs'; import yargs from 'yargs';
const {uniqueNamesGenerator, starWars, adjectives, animals} = require('unique-names-generator'); const {
uniqueNamesGenerator,
starWars,
adjectives,
animals
} = require('unique-names-generator');
/* get cli args */ /* get cli args */
const args = yargs const args = yargs
.alias('u', 'url') .alias('u', 'url')
.alias('m', 'module') .alias('m', 'module')
.alias('n', 'nomodel') .alias('n', 'nomodel')
.help('help') .help('help').argv;
.argv;
/* cwd is reference to all commands */ /* cwd is reference to all commands */
args.folder = process.cwd(); args.folder = process.cwd();
/* handle command */ /* handle command */
(async () => { (async () => {
// Checks for available update and returns an instance
const notifier = updateNotifier({ pkg });
// Checks for available update and returns an instance // Notify using the built-in convenience method
const notifier = updateNotifier({pkg});
// Notify using the built-in convenience method
notifier.notify(); notifier.notify();
if (args._) { if (args._) {
if (!args._.length) { if (!args._.length) {
await SocialMgr.showPrompt(); await SocialMgr.showPrompt();
args._.unshift(uniqueNamesGenerator({ args._.unshift(
dictionaries: [[starWars], [adjectives, animals]][Math.floor(Math.random() * 2)] uniqueNamesGenerator({
}).toLowerCase().replace(/[ -]/g, '_')); dictionaries: [[starWars], [adjectives, animals]][
Math.floor(Math.random() * 2)
]
})
.toLowerCase()
.replace(/[ -]/g, '_')
);
} }
await CliMgr.process(args); await CliMgr.process(args);
} else { } else {
Util.showHelp(args); Util.showHelp(args);
process.exit(0) process.exit(0);
} }
})().catch(err => { })().catch(err => {
console.error('\n\nThere was an error processing command:'); console.error('\n\nThere was an error processing command:');
console.error(err); console.error(err);
}); });

19
packages/nc-cli/src/lib/CliMgr.ts

@ -12,14 +12,13 @@ import client from './mgr/Client';
// import PermissionsMgr from './mgr/PermissionsMgr'; // import PermissionsMgr from './mgr/PermissionsMgr';
// import SocialMgr from './mgr/SocialMgr'; // import SocialMgr from './mgr/SocialMgr';
// import DockerMgr from "./mgr/DockerMgr"; // import DockerMgr from "./mgr/DockerMgr";
import NewMgr from "./mgr/NewMgr"; import NewMgr from './mgr/NewMgr';
// import TryMgr from "./mgr/TryMgr"; // import TryMgr from "./mgr/TryMgr";
let cmdProcessedOnce = 0; let cmdProcessedOnce = 0;
let cmdOriginalArgs = null; let cmdOriginalArgs = null;
class CliMgr { class CliMgr {
public static async runCmd(str) { public static async runCmd(str) {
shell.echo(`\nNow, executing command : ${str}\n\n`.blue); shell.echo(`\nNow, executing command : ${str}\n\n`.blue);
if (shell.exec(str).code !== 0) { if (shell.exec(str).code !== 0) {
@ -30,13 +29,11 @@ class CliMgr {
} }
public static async process(args) { public static async process(args) {
cmdOriginalArgs = cmdOriginalArgs ? cmdOriginalArgs : args; cmdOriginalArgs = cmdOriginalArgs ? cmdOriginalArgs : args;
try { try {
if (args._ && args._.length) { if (args._ && args._.length) {
switch (args._[0]) { switch (args._[0]) {
case 'man': case 'man':
if (args._.length > 1) { if (args._.length > 1) {
Util.showHelpForCommand(args); Util.showHelpForCommand(args);
@ -53,11 +50,11 @@ class CliMgr {
if (await NewMgr.getNewProjectInput(args)) { if (await NewMgr.getNewProjectInput(args)) {
if (args._[0] === 'gap') { if (args._[0] === 'gap') {
console.log('gRPC code generation is not yet supported.'); console.log('gRPC code generation is not yet supported.');
process.exit(0) process.exit(0);
} }
await client.requestSend(args) await client.requestSend(args);
} else { } else {
process.exit(0) process.exit(0);
} }
break; break;
@ -405,7 +402,6 @@ class CliMgr {
// process.exit(0) // process.exit(0)
// break; // break;
default: default:
if (!cmdProcessedOnce) { if (!cmdProcessedOnce) {
cmdProcessedOnce = 1; cmdProcessedOnce = 1;
@ -413,9 +409,11 @@ class CliMgr {
args._.unshift('new'); args._.unshift('new');
await this.process(args); await this.process(args);
} else { } else {
console.log(`\nUnknown command. ${cmdOriginalArgs._[0]} -- please see help below`); console.log(
`\nUnknown command. ${cmdOriginalArgs._[0]} -- please see help below`
);
Util.showHelp(cmdOriginalArgs); Util.showHelp(cmdOriginalArgs);
process.exit(0) process.exit(0);
} }
break; break;
} }
@ -427,4 +425,3 @@ class CliMgr {
} }
export default CliMgr; export default CliMgr;

77
packages/nc-cli/src/lib/mgr/AppMgr.ts

@ -11,11 +11,14 @@ import('colors');
const PROGRESS_WIDTH = 30; const PROGRESS_WIDTH = 30;
class AppMgr { class AppMgr {
public static async install(args) { public static async install(args) {
try { try {
const spinner = ora({text: 'Downloading Desktop App from Github..'.green.bold(), spinner: 'dots2', color: 'green'}).start(); const spinner = ora({
const {src, dest} = await AppMgr.getDownloadLink(args); text: 'Downloading Desktop App from Github..'.green.bold(),
spinner: 'dots2',
color: 'green'
}).start();
const { src, dest } = await AppMgr.getDownloadLink(args);
console.log(`\t${src}`); console.log(`\t${src}`);
@ -23,20 +26,25 @@ class AppMgr {
// console.log(progress) // console.log(progress)
// Report download progress // Report download progress
const p = PROGRESS_WIDTH * progress.percent; const p = PROGRESS_WIDTH * progress.percent;
spinner.text = `Downloading Desktop App now..\n[${ spinner.text = `Downloading Desktop App now..\n[${Array.from(
Array.from({length: PROGRESS_WIDTH}, (_, i) => i <= p ? '=' : ' ').join('') { length: PROGRESS_WIDTH },
}] ${(progress.transferred / (1024 * 1024)).toFixed(2)}MB/${(progress.total / (1024 * 1024)).toFixed(2)}MB\n`.green.bold() (_, i) => (i <= p ? '=' : ' ')
).join('')}] ${(progress.transferred / (1024 * 1024)).toFixed(2)}MB/${(
progress.total /
(1024 * 1024)
).toFixed(2)}MB\n`.green.bold();
}); });
// spinner.prefixText = ''; // spinner.prefixText = '';
spinner.succeed(`Installable downloaded successfully at ./${dest}`.green.bold()); spinner.succeed(
`Installable downloaded successfully at ./${dest}`.green.bold()
);
console.log(`\nInstallable will open automatically now.`.green.bold); console.log(`\nInstallable will open automatically now.`.green.bold);
console.log(`If not, please install it manually.`.green.bold); console.log(`If not, please install it manually.`.green.bold);
if (os.type() === 'Windows_NT') { if (os.type() === 'Windows_NT') {
// open(dest, {wait: true, app: 'explorer.exe'}) // open(dest, {wait: true, app: 'explorer.exe'})
} else { } else {
open(dest, {wait: true}); open(dest, { wait: true });
} }
} catch (e) { } catch (e) {
console.error(`Error in xc app.install`, e); console.error(`Error in xc app.install`, e);
} }
@ -45,7 +53,9 @@ class AppMgr {
public static async open(args) { public static async open(args) {
try { try {
const runCommand = AppMgr.getOpenCommand(args); const runCommand = AppMgr.getOpenCommand(args);
if (!runCommand) { return } if (!runCommand) {
return;
}
if (shell.exec(runCommand).code !== 0) { if (shell.exec(runCommand).code !== 0) {
shell.echo(`\n\nError running command internally`.red); shell.echo(`\n\nError running command internally`.red);
shell.echo(`\nExiting...`.red); shell.echo(`\nExiting...`.red);
@ -56,20 +66,27 @@ class AppMgr {
} }
} }
public static async getDownloadLink(args):Promise<any> { public static async getDownloadLink(args): Promise<any> {
try { try {
let src; let src;
let dest; let dest;
const urls:any = {}; const urls: any = {};
const res = await axios.get('https://api.github.com/repos/xgenecloud/xc-desktop-app/releases?page=1') const res = await axios.get(
'https://api.github.com/repos/xgenecloud/xc-desktop-app/releases?page=1'
);
let status = 0; let status = 0;
for (let i = 0; i < res.data.length && status !== 15; i++) { for (let i = 0; i < res.data.length && status !== 15; i++) {
const assets = res.data[i].assets; const assets = res.data[i].assets;
for (const {name, browser_download_url} of assets) { for (const { name, browser_download_url } of assets) {
switch (name.split('.').pop().toLowerCase()) { switch (
name
.split('.')
.pop()
.toLowerCase()
) {
case 'dmg': case 'dmg':
urls.dmg = urls.dmg || browser_download_url; urls.dmg = urls.dmg || browser_download_url;
status = status | 1; status = status | 1;
@ -92,20 +109,22 @@ class AppMgr {
switch (os.type()) { switch (os.type()) {
case 'Linux': case 'Linux':
const linuxInfo = osInfo({mode: 'sync'}); const linuxInfo = osInfo({ mode: 'sync' });
if (args.debian) { src = urls.deb; } if (args.debian) {
else if (args.rpm) { src = urls.rpm; } src = urls.deb;
else { } else if (args.rpm) {
src = urls.rpm;
} else {
switch (linuxInfo.id) { switch (linuxInfo.id) {
case 'ubuntu': case 'ubuntu':
case 'raspberry': case 'raspberry':
src = urls.deb src = urls.deb;
break; break;
case 'fedora': case 'fedora':
src = urls.rpm src = urls.rpm;
break; break;
default: default:
src = urls.rpm src = urls.rpm;
} }
} }
break; break;
@ -120,22 +139,22 @@ class AppMgr {
} }
dest = src.split('/').pop(); dest = src.split('/').pop();
return {src, dest} return { src, dest };
} catch (e) { } catch (e) {
console.log(e) console.log(e);
} }
} }
public static getOpenCommand(_args):any { public static getOpenCommand(_args): any {
switch (os.type()) { switch (os.type()) {
case 'Linux': case 'Linux':
return 'xgenecloud' return 'xgenecloud';
break; break;
case 'Darwin': case 'Darwin':
return 'open -a xgenecloud' return 'open -a xgenecloud';
break; break;
case 'Windows_NT': case 'Windows_NT':
console.info('Open xgenecloud desktop app from Windows start menu') console.info('Open xgenecloud desktop app from Windows start menu');
break; break;
default: default:
@ -144,6 +163,4 @@ class AppMgr {
} }
} }
export default AppMgr; export default AppMgr;

41
packages/nc-cli/src/lib/mgr/Client.ts

@ -9,18 +9,11 @@ import shell from 'shelljs';
// import {CmdSocketServer} from 'nc-help'; // import {CmdSocketServer} from 'nc-help';
// import SocialMgr from './SocialMgr'; // import SocialMgr from './SocialMgr';
class Client { class Client {
public static async requestSend(_args) { public static async requestSend(_args) {
try { try {
// await CmdSocketServer.cmdHandler(null, null, args); // await CmdSocketServer.cmdHandler(null, null, args);
// const portOpen = await tcpPortUsed.check(config.port, 'localhost'); // const portOpen = await tcpPortUsed.check(config.port, 'localhost');
// if (portOpen) { // if (portOpen) {
// //
// // client.emit('__REQUEST__', args); // // client.emit('__REQUEST__', args);
@ -28,7 +21,6 @@ class Client {
// await promprRunOrDownload.handle(args) // await promprRunOrDownload.handle(args)
// process.exit(0); // process.exit(0);
// } // }
} catch (e) { } catch (e) {
console.log('Error generating code.', e.message); console.log('Error generating code.', e.message);
throw e; throw e;
@ -37,7 +29,6 @@ class Client {
} }
public static async runCmd(str): Promise<any> { public static async runCmd(str): Promise<any> {
shell.echo(`\nNow, executing command : ${str}\n\n`.blue); shell.echo(`\nNow, executing command : ${str}\n\n`.blue);
const code = shell.exec(str).code; const code = shell.exec(str).code;
if (code !== 0) { if (code !== 0) {
@ -45,16 +36,12 @@ class Client {
// shell.echo(`\nExiting...`.red); // shell.echo(`\nExiting...`.red);
shell.exit(1); shell.exit(1);
} }
return 0 return 0;
} }
public static async responseHandle(args) { public static async responseHandle(args) {
try { try {
switch (args._[0]) { switch (args._[0]) {
case 'ga': case 'ga':
case 'gar': case 'gar':
case 'gen.apis': case 'gen.apis':
@ -65,19 +52,29 @@ class Client {
if (!args.err) { if (!args.err) {
// SocialMgr.setCreatedApis(true) // SocialMgr.setCreatedApis(true)
if (os.type() === 'Windows_NT') { if (os.type() === 'Windows_NT') {
console.log(boxen(`# APIs generated successfully\n\n# Please run the following commands\n${('cd ' + path.dirname(args.folder) + '; npm install ; npm run dev\n').green.bold}`, { console.log(
boxen(
`# APIs generated successfully\n\n# Please run the following commands\n${
(
'cd ' +
path.dirname(args.folder) +
'; npm install ; npm run dev\n'
).green.bold
}`,
{
borderColor: 'green', borderColor: 'green',
borderStyle: 'round', borderStyle: 'round',
margin: 1, margin: 1,
padding: 1 padding: 1
} as any)); } as any
)
);
} else { } else {
await Client.runCmd(`npm install; npm run dev;`); await Client.runCmd(`npm install; npm run dev;`);
} }
} }
break; break;
case 'gc': case 'gc':
case 'gen.controller': case 'gen.controller':
break; break;
@ -123,10 +120,10 @@ class Client {
case 'm': case 'm':
break; break;
case 'db.migrate.sql.dump' : case 'db.migrate.sql.dump':
case 'dmm' : case 'dmm':
case 'dmmd' : case 'dmmd':
console.log('db.migrate.sql.dump finished') console.log('db.migrate.sql.dump finished');
break; break;
default: default:
@ -136,7 +133,6 @@ class Client {
throw e; throw e;
} }
} }
} }
// //
@ -162,4 +158,3 @@ class Client {
// //
export default Client; export default Client;

26
packages/nc-cli/src/lib/mgr/ComponentMgr.ts

@ -2,36 +2,30 @@ import inquirer from 'inquirer';
import path from 'path'; import path from 'path';
class ComponentMgr { class ComponentMgr {
public static async add(_args) { public static async add(_args) {
const components = require(path.join(
process.cwd(),
'./server/app.components.js'
));
const components = require(path.join(process.cwd(), './server/app.components.js')) const answer = await inquirer.prompt([
const answer = await inquirer
.prompt([
{ {
choices: components.components.map(component => component.title), choices: components.components.map(component => component.title),
message: 'Choose after which component should we insert the new component?', message:
'Choose after which component should we insert the new component?',
name: 'compoonent', name: 'compoonent',
type: 'list' type: 'list'
} }
]) ]);
return answer.compoonent; return answer.compoonent;
} }
// tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty
public static async rename(_args) { public static async rename(_args) {}
}
// tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty
public static async delete(_args) { public static async delete(_args) {}
}
} }
export default ComponentMgr; export default ComponentMgr;

26
packages/nc-cli/src/lib/mgr/DockerMgr.ts

@ -1,23 +1,21 @@
import NewMgr from "./NewMgr"; import NewMgr from './NewMgr';
import('colors'); import('colors');
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
class DockerMgr extends NewMgr { class DockerMgr extends NewMgr {
public static async genDockerfile(args: any) { public static async genDockerfile(args: any) {
const dockerFilePath = path.join(process.cwd(), 'Dockerfile'); const dockerFilePath = path.join(process.cwd(), 'Dockerfile');
try { try {
args._.push('placeholder') args._.push('placeholder');
if(await this.getNewProjectInput(args)) { if (await this.getNewProjectInput(args)) {
const dockerfileContent = this.getDockerfileContent(args); const dockerfileContent = this.getDockerfileContent(args);
fs.writeFileSync(dockerFilePath, dockerfileContent); fs.writeFileSync(dockerFilePath, dockerfileContent);
console.log(`Docker file created successfully`.green.bold) console.log(`Docker file created successfully`.green.bold);
console.log(`\tFile location : ${dockerFilePath}`.green) console.log(`\tFile location : ${dockerFilePath}`.green);
console.log(`\tdocker build . -t xc`.green.bold) console.log(`\tdocker build . -t xc`.green.bold);
}else{ } else {
// console.log('Database connection failed') // console.log('Database connection failed')
} }
} catch (e) { } catch (e) {
@ -31,14 +29,12 @@ class DockerMgr extends NewMgr {
ENV PORT 8080 ENV PORT 8080
ENV NODE_ENV=dev ENV NODE_ENV=dev
ENV TOOL_DIR=/tool ENV TOOL_DIR=/tool
${ ${args.url
args.url.map((url, i) => `ENV DB_URL${i > 0 ? i + 1 : ''}=${url}`).join('\r\n') .map((url, i) => `ENV DB_URL${i > 0 ? i + 1 : ''}=${url}`)
} .join('\r\n')}
` `;
} }
} }
export default DockerMgr; export default DockerMgr;

23
packages/nc-cli/src/lib/mgr/InstantMgr.ts

@ -4,7 +4,7 @@
// import path from 'path'; // import path from 'path';
// import URL from 'url'; // import URL from 'url';
import express from 'express'; import express from 'express';
import {XcApis, XcConfigFactory,} from "xc-instant"; import { XcApis, XcConfigFactory } from 'xc-instant';
import('colors'); import('colors');
@ -42,28 +42,28 @@ import('colors');
// }; // };
class InstantMgr { class InstantMgr {
public static async getNewProjectInput(args): Promise<any> { public static async getNewProjectInput(args): Promise<any> {
if (args._.length < 2) { if (args._.length < 2) {
const usage = '\n$ xc instant "mysql://localhost:3306?u=root&p=password&d=database&a=rest"'.green.bold const usage = '\n$ xc instant "mysql://localhost:3306?u=root&p=password&d=database&a=rest"'
console.log(`\n\nWarning! missing connection URL\n\nExample Usage:\n${usage}\n`.red.bold); .green.bold;
console.log(
`\n\nWarning! missing connection URL\n\nExample Usage:\n${usage}\n`.red
.bold
);
return false; return false;
} }
const config = XcConfigFactory.makeFromUrls(args._.slice(1));
const config = XcConfigFactory.makeFromUrls(args._.slice(1))
const server = express(); const server = express();
server.set('view engine', 'ejs'); server.set('view engine', 'ejs');
const app = new XcApis(config) const app = new XcApis(config);
server.use(await app.init()); server.use(await app.init());
server.listen('8080', () => console.log('App started')); server.listen('8080', () => console.log('App started'));
// /* Construct database URL from prompt */ // /* Construct database URL from prompt */
// const dbTypes = Object.keys(dbDefaults); // const dbTypes = Object.keys(dbDefaults);
// args.url = [] // args.url = []
@ -210,10 +210,8 @@ class InstantMgr {
// args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag'; // args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag';
// args.url.push(url); // args.url.push(url);
// return NewMgr.testConnection(args) // return NewMgr.testConnection(args)
} }
// public static async testConnection({url}) { // public static async testConnection({url}) {
// //
// for (const u of url) { // for (const u of url) {
@ -243,7 +241,6 @@ class InstantMgr {
// return true; // return true;
// } // }
// public static async isPortOpen(host, port) { // public static async isPortOpen(host, port) {
// try { // try {
// return await tcpPortUsed.check(+port, host) // return await tcpPortUsed.check(+port, host)
@ -253,8 +250,6 @@ class InstantMgr {
// return true; // return true;
// } // }
// } // }
} }
export default InstantMgr; export default InstantMgr;

50
packages/nc-cli/src/lib/mgr/MigrationMgr.ts

@ -1,15 +1,14 @@
import {Migrator} from 'xc-migrator-ts'; import { Migrator } from 'xc-migrator-ts';
const migrator = new Migrator() const migrator = new Migrator();
class MigrationMgr { class MigrationMgr {
public static _getFolder(args) { public static _getFolder(args) {
args.folder = args.folder || process.cwd(); args.folder = args.folder || process.cwd();
} }
public static async init(args) { public static async init(args) {
try { try {
args.type = args.type || "mysql"; args.type = args.type || 'mysql';
await migrator.init(args); await migrator.init(args);
} catch (e) { } catch (e) {
console.log('db.migrate.init : Error occured', e); console.log('db.migrate.init : Error occured', e);
@ -27,9 +26,9 @@ class MigrationMgr {
public static async create(args) { public static async create(args) {
try { try {
this._getFolder(args) this._getFolder(args);
await migrator.migrationsCreate({ await migrator.migrationsCreate({
dbAlias: args.dbAlias || "primary", dbAlias: args.dbAlias || 'primary',
folder: args.folder folder: args.folder
}); });
} catch (e) { } catch (e) {
@ -38,10 +37,8 @@ class MigrationMgr {
} }
public static async up(args) { public static async up(args) {
try { try {
this._getFolder(args);
this._getFolder(args)
let migrationSteps = args.steps || 9999; let migrationSteps = args.steps || 9999;
@ -49,27 +46,24 @@ class MigrationMgr {
migrationSteps = 0; migrationSteps = 0;
} }
const migratorInst = new Migrator() const migratorInst = new Migrator();
await migratorInst.migrationsUp({ await migratorInst.migrationsUp({
dbAlias: args.dbAlias || "primary", dbAlias: args.dbAlias || 'primary',
env: args.env || "dev", env: args.env || 'dev',
file: args.file || null, file: args.file || null,
folder: args.folder, folder: args.folder,
migrationSteps, migrationSteps,
onlyList: args.list, onlyList: args.list,
sqlContentMigrate: (+args.sqlContentMigrate === 0 ? 0 : 1) sqlContentMigrate: +args.sqlContentMigrate === 0 ? 0 : 1
}); });
} catch (e) { } catch (e) {
console.log('db.migrate.up : Error occured', e); console.log('db.migrate.up : Error occured', e);
} }
} }
public static async down(args) { public static async down(args) {
try { try {
this._getFolder(args);
this._getFolder(args)
let migrationSteps = args.steps || 9999; let migrationSteps = args.steps || 9999;
@ -78,25 +72,22 @@ class MigrationMgr {
} }
await migrator.migrationsDown({ await migrator.migrationsDown({
dbAlias: args.dbAlias || "primary", dbAlias: args.dbAlias || 'primary',
env: args.env || "dev", env: args.env || 'dev',
file: args.file || null, file: args.file || null,
folder: args.folder, folder: args.folder,
migrationSteps, migrationSteps,
onlyList: args.list, onlyList: args.list,
sqlContentMigrate: (+args.sqlContentMigrate === 0 ? 0 : 1) sqlContentMigrate: +args.sqlContentMigrate === 0 ? 0 : 1
}); });
} catch (e) { } catch (e) {
console.log('db.migrate.down : Error occured', e); console.log('db.migrate.down : Error occured', e);
} }
} }
public static async list(args) { public static async list(args) {
try { try {
this._getFolder(args);
this._getFolder(args)
let migrationSteps = args.steps || 9999; let migrationSteps = args.steps || 9999;
@ -105,8 +96,8 @@ class MigrationMgr {
} }
const data = await migrator.migrationsUp({ const data = await migrator.migrationsUp({
dbAlias: args.dbAlias || "primary", dbAlias: args.dbAlias || 'primary',
env: args.env || "dev", env: args.env || 'dev',
file: args.file || null, file: args.file || null,
folder: args.folder, folder: args.folder,
migrationSteps, migrationSteps,
@ -114,25 +105,20 @@ class MigrationMgr {
}); });
console.log(data.data.object.list); console.log(data.data.object.list);
} catch (e) { } catch (e) {
console.log('db.migrate.up : Error occured', e); console.log('db.migrate.up : Error occured', e);
} }
} }
public static async clean(args) { public static async clean(args) {
try { try {
args.type = args.type || "mysql"; args.type = args.type || 'mysql';
await migrator.clean(args); await migrator.clean(args);
} catch (e) { } catch (e) {
console.log('db.migrate.clean : Error occured', e); console.log('db.migrate.clean : Error occured', e);
} }
} }
} }
// expose class // expose class
export default MigrationMgr; export default MigrationMgr;

44
packages/nc-cli/src/lib/mgr/ModelMgr.ts

@ -3,8 +3,6 @@ import glob from 'glob';
import path from 'path'; import path from 'path';
class ModelMgr { class ModelMgr {
/*** /***
* *
* @param args * @param args
@ -18,25 +16,43 @@ class ModelMgr {
args.dbAlias = args.dbAlias || '*'; args.dbAlias = args.dbAlias || '*';
if (args.models) { if (args.models) {
for (const model of args.models.split('.')) { for (const model of args.models.split('.')) {
for (const file of glob.sync(path.join(args.folder, 'server', 'models', args.dbAlias,model, `${model}.meta.*.js`))) { for (const file of glob.sync(
await fsExtra.remove(file) path.join(
console.log(`Removed successfully : ${path.basename(file)}`.green.bold) args.folder,
'server',
'models',
args.dbAlias,
model,
`${model}.meta.*.js`
)
)) {
await fsExtra.remove(file);
console.log(
`Removed successfully : ${path.basename(file)}`.green.bold
);
} }
} }
} else { } else {
for (const file of glob.sync(path.join(args.folder, 'server', 'models', args.dbAlias, '*', '*.meta.*.js'))) { for (const file of glob.sync(
await fsExtra.remove(file) path.join(
console.log(`Removed successfully : ${path.basename(file)}`.green.bold) args.folder,
'server',
'models',
args.dbAlias,
'*',
'*.meta.*.js'
)
)) {
await fsExtra.remove(file);
console.log(
`Removed successfully : ${path.basename(file)}`.green.bold
);
} }
} }
}catch (e) { } catch (e) {
console.log(`Error while removing backup file`.red.bold) console.log(`Error while removing backup file`.red.bold);
} }
} }
} }
export default ModelMgr; export default ModelMgr;

400
packages/nc-cli/src/lib/mgr/NewMgr.ts

@ -5,14 +5,14 @@ import mkdirp from 'mkdirp';
import path from 'path'; import path from 'path';
import tcpPortUsed from 'tcp-port-used'; import tcpPortUsed from 'tcp-port-used';
import URL from 'url'; import URL from 'url';
import {promisify} from "util"; import { promisify } from 'util';
import Util from "../util/Util"; import Util from '../util/Util';
import {v4 as uuidv4} from 'uuid'; import boxen from 'boxen';
import * as fs from "fs"; import * as fs from 'fs';
import Lang, {STR} from "../util/Lang";
import os from 'os'; import os from 'os';
import boxen from "boxen"; import { v4 as uuidv4 } from 'uuid';
import Lang, { STR } from '../util/Lang';
// @ts-ignore // @ts-ignore
const colors = require('colors'); const colors = require('colors');
@ -45,7 +45,7 @@ const dbDefaults = {
username: 'sa', username: 'sa',
password: '', password: '',
database: '' database: ''
}, }
}; };
// const apiTypeMapping = { // const apiTypeMapping = {
@ -58,9 +58,7 @@ const dbDefaults = {
// 'Typescript': 'ts', // 'Typescript': 'ts',
// } // }
class NewMgr { class NewMgr {
/** /**
* *
* Does the below : * Does the below :
@ -73,24 +71,28 @@ class NewMgr {
* @returns {Promise<string|string|boolean|*>} * @returns {Promise<string|string|boolean|*>}
*/ */
public static async getNewProjectInput(args): Promise<any> { public static async getNewProjectInput(args): Promise<any> {
if (args._.length < 2) { if (args._.length < 2) {
const usage = '\n$ xc new project_name'.green.bold const usage = '\n$ xc new project_name'.green.bold;
console.log(`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red.bold); console.log(
`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red
.bold
);
return false; return false;
} }
/* Construct database URL from prompt */ /* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults); const dbTypes = Object.keys(dbDefaults);
args.url = [] args.url = [];
console.log(`NocoDB requires a database to store metadata of database-spreadsheets.\nPlease enter the database credentials (defaults to SQLite3)`.green.bold) console.log(
const answers = await inquirer `NocoDB requires a database to store metadata of database-spreadsheets.\nPlease enter the database credentials (defaults to SQLite3)`
.prompt([ .green.bold
);
const answers = await inquirer.prompt([
{ {
name: 'type', name: 'type',
type: 'list', type: 'list',
message: Lang.getString(STR.DB_TYPE),// '🔥 Choose SQL Database type\t:', message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({ choices: dbTypes.map(t => ({
name: t, name: t,
value: t, value: t,
@ -104,49 +106,57 @@ class NewMgr {
{ {
name: 'host', name: 'host',
type: 'input', type: 'input',
message: Lang.getString(STR.DB_HOST),// '👉 Enter database host name\t:', message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].host return dbDefaults[ans.type].host;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
name: 'port', name: 'port',
type: 'number', type: 'number',
message: Lang.getString(STR.DB_PORT),// '👉 Enter database port number\t:', message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].port return dbDefaults[ans.type].port;
}, },
transformer(color) { transformer(color) {
try { try {
return color.green.bold; return color.green.bold;
} catch (e) { } catch (e) {
return color return color;
} }
}, },
validate(port, answers) { validate(port, answers) {
const done = this.async(); const done = this.async();
if (answers.host === 'host.docker.internal' || answers.host === 'docker.for.win.localhost') { if (
done(null, true) answers.host === 'host.docker.internal' ||
answers.host === 'docker.for.win.localhost'
) {
done(null, true);
} else { } else {
NewMgr.isPortOpen(answers.host, port).then(isOpen => { NewMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) { if (isOpen) {
done(null, true) done(null, true);
} else { } else {
// done('Port is not open') // done('Port is not open')
console.log(`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`.red.bold) console.log(
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
.red.bold
);
process.exit(0); process.exit(0);
} }
}).catch(done) })
.catch(done);
} }
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -154,13 +164,13 @@ class NewMgr {
type: 'input', type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:', message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].username return dbDefaults[ans.type].username;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -169,10 +179,10 @@ class NewMgr {
mask: true, mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:', message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) { transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('') return new Array(color.length).fill('*'.green.bold).join('');
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -185,8 +195,8 @@ class NewMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
@ -194,7 +204,9 @@ class NewMgr {
name: 'projectType', name: 'projectType',
type: 'list', type: 'list',
message: Lang.getString(STR.PROJECT_TYPE), // '🚀 How do you want to run it\t:', message: Lang.getString(STR.PROJECT_TYPE), // '🚀 How do you want to run it\t:',
choices: [ 'As Node.js Project','As Docker', //'Try XC Instant App (Without scaffolding code)' choices: [
'As Node.js Project',
'As Docker' // 'Try XC Instant App (Without scaffolding code)'
].map(t => ({ ].map(t => ({
name: t, name: t,
value: t, value: t,
@ -202,14 +214,15 @@ class NewMgr {
})), })),
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, }
}, }
]) ]);
/* if not valid retry getting right input */ /* if not valid retry getting right input */
if (answers.type !== 'sqlite3' && !answers.database) { if (answers.type !== 'sqlite3' && !answers.database) {
console.log('\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold); console.log(
'\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold
);
this.getNewProjectInput(args); this.getNewProjectInput(args);
} }
@ -226,67 +239,93 @@ class NewMgr {
} }
if (answers.projectType === 'mvc' && !answers.isForExisting) { if (answers.projectType === 'mvc' && !answers.isForExisting) {
/* attach new project name to path and 'cd' to that folder */ /* attach new project name to path and 'cd' to that folder */
args.folder = path.join(args.folder, args._[1]); args.folder = path.join(args.folder, args._[1]);
mkdirp.sync(args.folder); mkdirp.sync(args.folder);
process.chdir(args.folder); process.chdir(args.folder);
await Util.runCmd(`cd ${Util.escapeShellArg(args.folder)}`); await Util.runCmd(`cd ${Util.escapeShellArg(args.folder)}`);
await promisify(download)('direct:https://github.com/nocodb/nocodb-seed/archive/refs/heads/main.zip', args.folder); await promisify(download)(
'direct:https://github.com/nocodb/nocodb-seed/archive/refs/heads/main.zip',
args.folder
);
if (answers.type !== 'sqlite3') { if (answers.type !== 'sqlite3') {
fs.appendFileSync(path.join(args.folder, '.env'), `NC_DB=${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`) fs.appendFileSync(
path.join(args.folder, '.env'),
`NC_DB=${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`
);
} }
if (os.type() === 'Windows_NT') { if (os.type() === 'Windows_NT') {
console.log(boxen(`# Project created successfully\n\n# Please run the following commands\n\n${('cd ' + Util.escapeShellArg(args.folder) + '\nnpm install \nnpm start\n').green.bold}`, { console.log(
boxen(
`# Project created successfully\n\n# Please run the following commands\n\n${
(
'cd ' +
Util.escapeShellArg(args.folder) +
'\nnpm install \nnpm start\n'
).green.bold
}`,
{
borderColor: 'green', borderColor: 'green',
borderStyle: 'round', borderStyle: 'round',
margin: 1, margin: 1,
padding: 1 padding: 1
} as any)); } as any
)
);
} else { } else {
await Util.runCmd(`npm install; npm run start;`); await Util.runCmd(`npm install; npm run start;`);
} }
} else if (answers.projectType) { } else if (answers.projectType) {
let env = ''; let env = '';
if (answers.type !== 'sqlite3') { if (answers.type !== 'sqlite3') {
env = `--env NC_DB="${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}"` env = `--env NC_DB="${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}"`;
} }
const linuxHost = os.type() === 'Linux' ? '--net=host' : ''; const linuxHost = os.type() === 'Linux' ? '--net=host' : '';
if (os.type() === 'Windows_NT') { if (os.type() === 'Windows_NT') {
// tslint:disable-next-line:ban-comma-operator // tslint:disable-next-line:ban-comma-operator
console.log(boxen(`# Please run the following docker commands\n\n${(`docker run -p 8080:8080 ${linuxHost} -d ${env} nocodb/nocodb:latest`).green.bold}\n`, { console.log(
boxen(
`# Please run the following docker commands\n\n${
`docker run -p 8080:8080 ${linuxHost} -d ${env} nocodb/nocodb:latest`
.green.bold
}\n`,
{
borderColor: 'green', borderColor: 'green',
borderStyle: 'round', borderStyle: 'round',
margin: 1, margin: 1,
padding: 1 padding: 1
} as any)); } as any
)
);
} else { } else {
await Util.runCmd(`docker run -p 8080:8080 ${linuxHost} -d ${env} nocodb/nocodb:latest`); await Util.runCmd(
`docker run -p 8080:8080 ${linuxHost} -d ${env} nocodb/nocodb:latest`
);
} }
} }
} }
public static async getNewProjectInputOld(args): Promise<any> { public static async getNewProjectInputOld(args): Promise<any> {
if (args._.length < 2) { if (args._.length < 2) {
const usage = '\n$ xc new project_name'.green.bold const usage = '\n$ xc new project_name'.green.bold;
console.log(`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red.bold); console.log(
`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red
.bold
);
return false; return false;
} }
/* Construct database URL from prompt */ /* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults); const dbTypes = Object.keys(dbDefaults);
args.url = [] args.url = [];
const answers = await inquirer const answers = await inquirer.prompt([
.prompt([
{ {
name: 'type', name: 'type',
type: 'list', type: 'list',
message: Lang.getString(STR.DB_TYPE),// '🔥 Choose SQL Database type\t:', message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({ choices: dbTypes.map(t => ({
name: t, name: t,
value: t, value: t,
@ -300,49 +339,57 @@ class NewMgr {
{ {
name: 'host', name: 'host',
type: 'input', type: 'input',
message: Lang.getString(STR.DB_HOST),// '👉 Enter database host name\t:', message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].host return dbDefaults[ans.type].host;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
name: 'port', name: 'port',
type: 'number', type: 'number',
message: Lang.getString(STR.DB_PORT),// '👉 Enter database port number\t:', message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].port return dbDefaults[ans.type].port;
}, },
transformer(color) { transformer(color) {
try { try {
return color.green.bold; return color.green.bold;
} catch (e) { } catch (e) {
return color return color;
} }
}, },
validate(port, answers) { validate(port, answers) {
const done = this.async(); const done = this.async();
if (answers.host === 'host.docker.internal' || answers.host === 'docker.for.win.localhost') { if (
done(null, true) answers.host === 'host.docker.internal' ||
answers.host === 'docker.for.win.localhost'
) {
done(null, true);
} else { } else {
NewMgr.isPortOpen(answers.host, port).then(isOpen => { NewMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) { if (isOpen) {
done(null, true) done(null, true);
} else { } else {
// done('Port is not open') // done('Port is not open')
console.log(`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`.red.bold) console.log(
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
.red.bold
);
process.exit(0); process.exit(0);
} }
}).catch(done) })
.catch(done);
} }
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -350,13 +397,13 @@ class NewMgr {
type: 'input', type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:', message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].username return dbDefaults[ans.type].username;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -365,10 +412,10 @@ class NewMgr {
mask: true, mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:', message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) { transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('') return new Array(color.length).fill('*'.green.bold).join('');
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -381,8 +428,8 @@ class NewMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -397,15 +444,20 @@ class NewMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
name: 'projectType', name: 'projectType',
type: 'list', type: 'list',
message: Lang.getString(STR.PROJECT_TYPE), // '🚀 How do you want to run it\t:', message: Lang.getString(STR.PROJECT_TYPE), // '🚀 How do you want to run it\t:',
choices: ['Docker', 'New Node.js project', 'Existing Node.js project', 'Try XC Instant App (Without scaffolding code)'].map(t => ({ choices: [
'Docker',
'New Node.js project',
'Existing Node.js project',
'Try XC Instant App (Without scaffolding code)'
].map(t => ({
name: t, name: t,
value: t, value: t,
short: t.green.bold short: t.green.bold
@ -413,10 +465,10 @@ class NewMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
}
} }
},
// { // {
// name: 'programmingLanguage', // name: 'programmingLanguage',
// type: 'list', // type: 'list',
@ -433,23 +485,24 @@ class NewMgr {
// return type !== 'sqlite3' // return type !== 'sqlite3'
// } // }
// } // }
]) ]);
// console.log(answers); // console.log(answers);
if (answers.type === 'sqlite3') { if (answers.type === 'sqlite3') {
console.log('Please use desktop app to create Sqlite project'.green.bold) console.log('Please use desktop app to create Sqlite project'.green.bold);
process.exit(0); process.exit(0);
} }
/* if not valid retry getting right input */ /* if not valid retry getting right input */
if (!answers.database) { if (!answers.database) {
console.log('\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold); console.log(
'\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold
);
this.getNewProjectInput(args); this.getNewProjectInput(args);
} }
// //
/* prepare the args */ /* prepare the args */
// const url = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&api=${apiTypeMapping[answers.projectType]}`; // const url = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&api=${apiTypeMapping[answers.projectType]}`;
// args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag'; // args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag';
@ -485,7 +538,6 @@ class NewMgr {
} }
if (answers.projectType === 'mvc' && !answers.isForExisting) { if (answers.projectType === 'mvc' && !answers.isForExisting) {
/* attach new project name to path and 'cd' to that folder */ /* attach new project name to path and 'cd' to that folder */
args.folder = path.join(args.folder, args._[1]); args.folder = path.join(args.folder, args._[1]);
mkdirp.sync(args.folder); mkdirp.sync(args.folder);
@ -495,72 +547,73 @@ class NewMgr {
await promisify(download)('gitlab:xc-public/test10', args.folder); await promisify(download)('gitlab:xc-public/test10', args.folder);
const config = { const config = {
title: args._[1], title: args._[1],
"version": "0.6", version: '0.6',
"envs": { envs: {
"dev": { dev: {
"db": [ db: [
{ {
"client": answers.type, client: answers.type,
"connection": { connection: {
"host": answers.host, host: answers.host,
"port": answers.port, port: answers.port,
"user": answers.username, user: answers.username,
"password": answers.password, password: answers.password,
"database": answers.database, database: answers.database,
"multipleStatements": true multipleStatements: true
}, },
"meta": { meta: {
"tn": "xc_evolutions", tn: 'xc_evolutions',
"dbAlias": "db", dbAlias: 'db',
"api": { api: {
"type": answers.apiType, type: answers.apiType,
"prefix": "", prefix: '',
"graphqlDepthLimit": 10 graphqlDepthLimit: 10
}, },
"inflection": { inflection: {
"tn": "none", tn: 'none',
"cn": "none" cn: 'none'
} }
} }
} }
], ],
"apiClient": { apiClient: {
"data": [] data: []
} }
} }
}, },
"workingEnv": "dev", workingEnv: 'dev',
"seedsFolder": "seeds", seedsFolder: 'seeds',
"queriesFolder": "queries", queriesFolder: 'queries',
"apisFolder": "apis", apisFolder: 'apis',
"projectType": answers.apiType, projectType: answers.apiType,
"type": "docker", type: 'docker',
"language": "ts", language: 'ts',
"apiClient": { apiClient: {
"data": [] data: []
}, },
"auth": { auth: {
"jwt": { jwt: {
"secret": uuidv4(), secret: uuidv4(),
"dbAlias": "db" dbAlias: 'db'
}
}, "meta": {
"db": {
"client": "sqlite3",
"connection": {
"filename": "xc.db"
} }
},
meta: {
db: {
client: 'sqlite3',
connection: {
filename: 'xc.db'
} }
} }
} }
};
fs.writeFileSync(path.join(args.folder, 'config.xc.json'), JSON.stringify(config, null, 2)) fs.writeFileSync(
path.join(args.folder, 'config.xc.json'),
JSON.stringify(config, null, 2)
);
await Util.runCmd(`npm install; npm run start;`); await Util.runCmd(`npm install; npm run start;`);
} else if (answers.projectType === 'mvc') { } else if (answers.projectType === 'mvc') {
console.log(` console.log(`
1. Install our npm package using following command 1. Install our npm package using following command
@ -568,7 +621,8 @@ class NewMgr {
2. Add the following code in your existing express project 2. Add the following code in your existing express project
\t${`const {Noco} = require("nocodb"); \t${
`const {Noco} = require("nocodb");
\tnew Noco({ \tnew Noco({
title: "${args._[1]}", title: "${args._[1]}",
@ -630,7 +684,8 @@ class NewMgr {
} }
} }
} }
}).init().then(mw => app.use(mw))`.green} }).init().then(mw => app.use(mw))`.green
}
@ -638,38 +693,33 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
`) `);
} else if (answers.projectType === 'docker') { } else if (answers.projectType === 'docker') {
const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`; const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`;
// console.log(` // console.log(`
// You can create docker container using following command // You can create docker container using following command
// //
// \t${`docker run -p 8080:8080 -p 8081:8081 -p 8082:8082 -d --name xc-instant --env DB_URL=${dbUrl} -d xgenecloud/xc:latest`.green} // \t${`docker run -p 8080:8080 -p 8081:8081 -p 8082:8082 -d --name xc-instant --env DB_URL=${dbUrl} -d xgenecloud/xc:latest`.green}
// //
// //
// Then visit http://localhost:8080/xc to access the Dashboard // Then visit http://localhost:8080/xc to access the Dashboard
// //
// `) // `)
const linuxHost = os.type() === 'Linux' ? '--net=host' : ''; const linuxHost = os.type() === 'Linux' ? '--net=host' : '';
await Util.runCmd(
await Util.runCmd(`docker run -p 8080:8080 -p 8081:8081 -p 8082:8082 ${linuxHost} --name xc-instant --env NC_DB_URL="${dbUrl}" xgenecloud/xc:latest`); `docker run -p 8080:8080 -p 8081:8081 -p 8082:8082 ${linuxHost} --name xc-instant --env NC_DB_URL="${dbUrl}" xgenecloud/xc:latest`
);
} }
// args.url.push(url); // args.url.push(url);
// //
// args.language = languageMapping[answers.programmingLanguage]; // args.language = languageMapping[answers.programmingLanguage];
// return OldNewMgr.testConnection(args) // return OldNewMgr.testConnection(args)
} }
public static async testConnection({ url }) {
public static async testConnection({url}) {
for (const u of url) { for (const u of url) {
const parsedUrlData = URL.parse(u, true); const parsedUrlData = URL.parse(u, true);
const queryParams = parsedUrlData.query; const queryParams = parsedUrlData.query;
@ -681,29 +731,30 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
port: +parsedUrlData.port, port: +parsedUrlData.port,
user: queryParams.u, user: queryParams.u,
password: queryParams.p, password: queryParams.p,
database: client === 'pg' ? 'postgres' : (client === 'mssql' ? undefined : null) database:
client === 'pg' ? 'postgres' : client === 'mssql' ? undefined : null
} }
}; };
try { try {
const knex = require('knex')(config) const knex = require('knex')(config);
await knex.raw("SELECT 1+1 as data"); await knex.raw('SELECT 1+1 as data');
} catch (e) { } catch (e) {
console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold) console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold);
return false; return false;
} }
} }
return true; return true;
} }
public static async isPortOpen(host, port) { public static async isPortOpen(host, port) {
try { try {
return await tcpPortUsed.check(+port, host) return await tcpPortUsed.check(+port, host);
} catch (e) { } catch (e) {
console.log(e) console.log(e);
console.log(`\n😩 ${host}:${port} is not reachable please check\n`.red.bold) console.log(
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
);
return true; return true;
} }
} }
@ -715,4 +766,3 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
} }
export default NewMgr; export default NewMgr;

122
packages/nc-cli/src/lib/mgr/OldNewMgr.ts

@ -6,7 +6,7 @@ import URL from 'url';
import('colors'); import('colors');
let tcpPortUsed = require('tcp-port-used'); const tcpPortUsed = require('tcp-port-used');
const dbDefaults = { const dbDefaults = {
mysql: { mysql: {
@ -36,22 +36,20 @@ const dbDefaults = {
username: 'sa', username: 'sa',
password: '', password: '',
database: '' database: ''
}, }
}; };
const apiTypeMapping = { const apiTypeMapping = {
'GRAPHQL APIs': 'graphql', 'GRAPHQL APIs': 'graphql',
'REST APIs': 'rest', 'REST APIs': 'rest',
'gRPC APIs': 'grpc' 'gRPC APIs': 'grpc'
} };
const languageMapping = { const languageMapping = {
'Javascript': 'js', Javascript: 'js',
'Typescript': 'ts', Typescript: 'ts'
} };
class OldNewMgr { class OldNewMgr {
/** /**
* *
* Does the below : * Does the below :
@ -64,19 +62,20 @@ class OldNewMgr {
* @returns {Promise<string|string|boolean|*>} * @returns {Promise<string|string|boolean|*>}
*/ */
public static async getNewProjectInput(args) { public static async getNewProjectInput(args) {
if (args._.length < 2) { if (args._.length < 2) {
const usage = '\n$ xc new project_name'.green.bold const usage = '\n$ xc new project_name'.green.bold;
console.log(`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red.bold); console.log(
`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red
.bold
);
return false; return false;
} }
/* Construct database URL from prompt */ /* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults); const dbTypes = Object.keys(dbDefaults);
args.url = [] args.url = [];
const answers = await inquirer const answers = await inquirer.prompt([
.prompt([
{ {
name: 'type', name: 'type',
type: 'list', type: 'list',
@ -96,13 +95,13 @@ class OldNewMgr {
type: 'input', type: 'input',
message: '👉 Enter database host name\t:', message: '👉 Enter database host name\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].host return dbDefaults[ans.type].host;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -110,29 +109,34 @@ class OldNewMgr {
type: 'number', type: 'number',
message: '👉 Enter database port number\t:', message: '👉 Enter database port number\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].port return dbDefaults[ans.type].port;
}, },
transformer(color) { transformer(color) {
try { try {
return color.green.bold; return color.green.bold;
} catch (e) { } catch (e) {
return color return color;
} }
}, },
validate(port, answers) { validate(port, answers) {
let done = this.async(); const done = this.async();
OldNewMgr.isPortOpen(answers.host, port).then(isOpen => { OldNewMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) { if (isOpen) {
done(null, true) done(null, true);
} else { } else {
// done('Port is not open') // done('Port is not open')
console.log(`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`.red.bold) console.log(
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
.red.bold
);
process.exit(0); process.exit(0);
} }
}).catch(done) })
.catch(done);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -140,13 +144,13 @@ class OldNewMgr {
type: 'input', type: 'input',
message: '👉 Enter database username\t:', message: '👉 Enter database username\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].username return dbDefaults[ans.type].username;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -155,10 +159,10 @@ class OldNewMgr {
mask: true, mask: true,
message: '🙈 Enter database password\t:', message: '🙈 Enter database password\t:',
transformer(color) { transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('') return new Array(color.length).fill('*'.green.bold).join('');
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -171,8 +175,8 @@ class OldNewMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -187,8 +191,8 @@ class OldNewMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -203,22 +207,24 @@ class OldNewMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
} }
]) ]);
// console.log(answers); // console.log(answers);
if (answers.type === 'sqlite3') { if (answers.type === 'sqlite3') {
console.log('Please use desktop app to create Sqlite project'.green.bold) console.log('Please use desktop app to create Sqlite project'.green.bold);
process.exit(0); process.exit(0);
} }
/* if not valid retry getting right input */ /* if not valid retry getting right input */
if (!answers.database) { if (!answers.database) {
console.log('\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold); console.log(
'\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold
);
this.getNewProjectInput(args); this.getNewProjectInput(args);
} }
@ -229,7 +235,11 @@ class OldNewMgr {
// await Util.runCmd(`cd ${args.folder}`); // await Util.runCmd(`cd ${args.folder}`);
/* prepare the args */ /* prepare the args */
const url = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&api=${apiTypeMapping[answers.projectType]}`; const url = `${answers.type}://${answers.host}:${answers.port}?u=${
answers.username
}&p=${answers.password}&d=${answers.database}&api=${
apiTypeMapping[answers.projectType]
}`;
args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag'; args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag';
switch (answers.projectType) { switch (answers.projectType) {
case 'REST APIs': case 'REST APIs':
@ -249,13 +259,10 @@ class OldNewMgr {
args.language = languageMapping[answers.programmingLanguage]; args.language = languageMapping[answers.programmingLanguage];
return OldNewMgr.testConnection(args) return OldNewMgr.testConnection(args);
} }
public static async testConnection({ url }) {
public static async testConnection({url}) {
for (const u of url) { for (const u of url) {
const parsedUrlData = URL.parse(u, true); const parsedUrlData = URL.parse(u, true);
const queryParams = parsedUrlData.query; const queryParams = parsedUrlData.query;
@ -267,34 +274,33 @@ class OldNewMgr {
port: +parsedUrlData.port, port: +parsedUrlData.port,
user: queryParams.u, user: queryParams.u,
password: queryParams.p, password: queryParams.p,
database: client === 'pg' ? 'postgres' : (client === 'mssql' ? undefined : null) database:
client === 'pg' ? 'postgres' : client === 'mssql' ? undefined : null
} }
}; };
try { try {
const knex = require('knex')(config) const knex = require('knex')(config);
await knex.raw("SELECT 1+1 as data"); await knex.raw('SELECT 1+1 as data');
} catch (e) { } catch (e) {
console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold) console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold);
return false; return false;
} }
} }
return true; return true;
} }
public static async isPortOpen(host, port) { public static async isPortOpen(host, port) {
try { try {
return await tcpPortUsed.check(+port, host) return await tcpPortUsed.check(+port, host);
} catch (e) { } catch (e) {
console.log(e) console.log(e);
console.log(`\n😩 ${host}:${port} is not reachable please check\n`.red.bold) console.log(
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
);
return true; return true;
} }
} }
} }
export default OldNewMgr; export default OldNewMgr;

516
packages/nc-cli/src/lib/mgr/PermissionsMgr.ts

@ -9,28 +9,29 @@ import Util from '../util/Util';
import Table from 'cli-table3'; import Table from 'cli-table3';
class PermissionsMgr { class PermissionsMgr {
public static async set(args) { public static async set(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 4) { if (args._.length < 4) {
console.warn('Invalid arguments for : xc permissions.set') console.warn('Invalid arguments for : xc permissions.set');
return; return;
} }
// @ts-ignore // @ts-ignore
let [_, models, users, ...resolvers] = args._; let [_, models, users, ...resolvers] = args._;
models = models.split('.'); models = models.split('.');
users = users.split('.'); users = users.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
if (models.includes(modelName) || models[0] === '$') { if (models.includes(modelName) || models[0] === '$') {
@ -40,73 +41,87 @@ class PermissionsMgr {
if (users[0] === '$') { if (users[0] === '$') {
for (const [route, rolesObj] of Object.entries(filePermissions)) { for (const [route, rolesObj] of Object.entries(filePermissions)) {
if (resolvers[0] === '$=1') { if (resolvers[0] === '$=1') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = true; obj[role] = true;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} resolver: ${route}`
);
} else if (resolvers[0] === '$=0') { } else if (resolvers[0] === '$=0') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = false; obj[role] = false;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} resolver: ${route}`
);
} else { } else {
resolvers.forEach(permission => { resolvers.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
if (route === permTuple[0]) { if (route === permTuple[0]) {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} , resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} , resolver: ${route}`
);
} }
}) });
} }
} }
} else { } else {
for (const [route, rolesObj] of Object.entries(filePermissions)) { for (const [route, rolesObj] of Object.entries(filePermissions)) {
resolvers.forEach(permission => { resolvers.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
if (route === permTuple[0] || permTuple[0] === '$') { if (route === permTuple[0] || permTuple[0] === '$') {
const permObj = users.reduce((obj, role) => { const permObj = users.reduce((obj, role) => {
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${users} , resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${users} , resolver: ${route}`
);
} }
}) });
} }
} }
const policyFileContent = `module.exports = ${JSON.stringify(filePermissions, null, 2)};\n`; const policyFileContent = `module.exports = ${JSON.stringify(
fs.writeFileSync(file, policyFileContent) filePermissions,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
} }
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.set`, e); console.error(`Error in xc permissions.set`, e);
} }
} else { } else {
try { try {
if (args._.length < 4) { if (args._.length < 4) {
console.warn('Invalid arguments for : xc permissions.set') console.warn('Invalid arguments for : xc permissions.set');
return; return;
} }
@ -117,72 +132,102 @@ class PermissionsMgr {
users = users.split('.'); users = users.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.routes.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.routes.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
if (models.includes(modelName) || models[0] === '$') { if (models.includes(modelName) || models[0] === '$') {
const routesList: Route[] = require(file); const routesList: Route[] = require(file);
const roles = this.extractUniqueRoles(routesList); const roles = this.extractUniqueRoles(routesList);
if (users[0] === '$') { if (users[0] === '$') {
for (const route of routesList) { for (const route of routesList) {
if (permissions[0] === '$=1') { if (permissions[0] === '$=1') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = true; obj[role] = true;
return obj; return obj;
}, {}); }, {});
Object.assign(route.acl, permObj) Object.assign(route.acl, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} method: ${route.type}=true, route: ${route.path}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} method: ${route.type}=true, route: ${route.path}`
);
} else if (permissions[0] === '$=0') { } else if (permissions[0] === '$=0') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = false; obj[role] = false;
return obj; return obj;
}, {}); }, {});
Object.assign(route.acl, permObj) Object.assign(route.acl, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} method: ${route.type}=false, route: ${route.path}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} method: ${route.type}=false, route: ${route.path}`
);
} else { } else {
permissions.forEach(permission => { permissions.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
if (route.type === permTuple[0]) { if (route.type === permTuple[0]) {
Object.assign(route.acl, permObj) Object.assign(route.acl, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} method: ${permTuple[0]}=${val}, route: ${route.path}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} method: ${permTuple[0]}=${val}, route: ${route.path}`
);
} }
}) });
} }
} }
} else { } else {
for (const route of routesList) { for (const route of routesList) {
permissions.forEach(permission => { permissions.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
const permObj = users.reduce((obj, role) => { const permObj = users.reduce((obj, role) => {
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
if (route.type === permTuple[0]) { if (route.type === permTuple[0]) {
Object.assign(route.acl, permObj) Object.assign(route.acl, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${users.join(', ')} method: ${permTuple[0]}=${val}, route: ${route.path}`); console.log(
`Setting Permissions for model:${modelName} roles:${users.join(
', '
)} method: ${permTuple[0]}=${val}, route: ${route.path}`
);
} else if (permTuple[0] === '*') { } else if (permTuple[0] === '*') {
Object.assign(route.acl, permObj) Object.assign(route.acl, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${users.join(', ')} method: ${route.type}=${val}, route: ${route.path}`); console.log(
`Setting Permissions for model:${modelName} roles:${users.join(
', '
)} method: ${route.type}=${val}, route: ${route.path}`
);
} }
}) });
} }
} }
const policyFileContent = `module.exports = ${JSON.stringify(routesList, null, 2)};\n`; const policyFileContent = `module.exports = ${JSON.stringify(
fs.writeFileSync(file, policyFileContent) routesList,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
} }
}); });
} catch (e) { } catch (e) {
@ -192,27 +237,30 @@ class PermissionsMgr {
} }
public static async get(args) { public static async get(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.get') console.warn('Invalid arguments for : xc permissions.get');
return; return;
} }
let {1: models} = args._; let { 1: models } = args._;
models = models.split('.'); models = models.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
// instantiate // instantiate
let rows: any[] = []; let rows: any[] = [];
let roles: any[] = []; let roles: any[] = [];
glob.sync(policiesPath).forEach(file => {
glob.sync(policiesPath).forEach((file) => {
// let filePermissions = require(file); // let filePermissions = require(file);
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
@ -220,25 +268,25 @@ class PermissionsMgr {
if (models.includes(modelName)) { if (models.includes(modelName)) {
const filePermissions = require(file); const filePermissions = require(file);
roles = this.extractUniqueGqlPolicyRoles(filePermissions); roles = this.extractUniqueGqlPolicyRoles(filePermissions);
rows.push([{ rows.push([
{
colSpan: roles.length + 1, colSpan: roles.length + 1,
content: colors.green(file), content: colors.green(file),
hAlign: 'center' hAlign: 'center'
}]) }
]);
for (const [route, methods] of Object.entries(filePermissions)) { for (const [route, methods] of Object.entries(filePermissions)) {
const row: any[] = [{content: route, vAlign: 'center'}]; const row: any[] = [{ content: route, vAlign: 'center' }];
for (const role of roles) { for (const role of roles) {
row.push(methods[role] ? colors.green('✔') : colors.red('x')); row.push(methods[role] ? colors.green('✔') : colors.red('x'));
} }
rows.push(row) rows.push(row);
} }
} }
}) });
const table = new Table({ const table = new Table({
head: ['Route', ...roles] head: ['Route', ...roles]
@ -246,111 +294,126 @@ class PermissionsMgr {
table.push(...rows); table.push(...rows);
console.log(table.toString()); console.log(table.toString());
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.get`, e); console.error(`Error in xc permissions.get`, e);
} }
} else { } else {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.get') console.warn('Invalid arguments for : xc permissions.get');
return; return;
} }
let {1: models} = args._; let { 1: models } = args._;
models = models.split('.'); models = models.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.routes.js'); const policiesPath = path.join(
process.cwd(),
'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.routes.js'
);
// instantiate // instantiate
const table = new Table({ const table = new Table({
head: ['Route', 'Role', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH'] head: ['Route', 'Role', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']
}); });
glob
glob.sync(policiesPath) .sync(policiesPath)
.sort(this.sortFiles) .sort(this.sortFiles)
.forEach((file) => { .forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
if (models.includes(modelName)) { if (models.includes(modelName)) {
const routesList: Route[] = require(file); const routesList: Route[] = require(file);
const groupedRoutes = this.groupRoutes(routesList); const groupedRoutes = this.groupRoutes(routesList);
// extract unique roles // extract unique roles
const roles = this.extractUniqueRoles(routesList); const roles = this.extractUniqueRoles(routesList);
table.push([{ table.push([
{
colSpan: 7, colSpan: 7,
content: colors.green(file), content: colors.green(file),
hAlign: 'center' hAlign: 'center'
}]) }
]);
for (const [routePath, methods] of Object.entries(groupedRoutes)) { for (const [routePath, methods] of Object.entries(
groupedRoutes
)) {
let i = 0; let i = 0;
for (const role of roles) { for (const role of roles) {
{ {
table.push([...(i++ ? [] : [{ table.push([
...(i++
? []
: [
{
content: routePath, content: routePath,
rowSpan: roles.length, rowSpan: roles.length,
vAlign: 'center' vAlign: 'center'
}]), role,
methods?.get?.acl?.[role] ? colors.green('✔') : colors.red('x'),
methods?.post?.acl?.[role] ? colors.green('✔') : colors.red('x'),
methods?.put?.acl?.[role] ? colors.green('✔') : colors.red('x'),
methods?.delete?.acl?.[role] ? colors.green('✔') : colors.red('x'),
methods?.patch?.acl?.[role] ? colors.green('✔') : colors.red('x'),
] as any)
} }
]),
role,
methods?.get?.acl?.[role]
? colors.green('✔')
: colors.red('x'),
methods?.post?.acl?.[role]
? colors.green('✔')
: colors.red('x'),
methods?.put?.acl?.[role]
? colors.green('✔')
: colors.red('x'),
methods?.delete?.acl?.[role]
? colors.green('✔')
: colors.red('x'),
methods?.patch?.acl?.[role]
? colors.green('✔')
: colors.red('x')
] as any);
} }
} }
} }
}
}) });
console.log(table.toString()); console.log(table.toString());
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.get`, e); console.error(`Error in xc permissions.get`, e);
} }
} }
} }
public static async userAdd(args) { public static async userAdd(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file); const filePermissions = require(file);
const roles = this.extractUniqueGqlPolicyRoles(filePermissions); const roles = this.extractUniqueGqlPolicyRoles(filePermissions);
if (roles.includes(user)) { if (roles.includes(user)) {
console.warn(`${user} already exist in ${modelName} policy`); console.warn(`${user} already exist in ${modelName} policy`);
return; return;
@ -360,42 +423,45 @@ class PermissionsMgr {
roles1[user] = true; roles1[user] = true;
} }
console.log(
`Adding new role permission for model:${modelName} roles:${user}`
);
console.log(`Adding new role permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports = ${JSON.stringify(
filePermissions,
null,
const policyFileContent = `module.exports = ${JSON.stringify(filePermissions, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.add`, e); console.error(`Error in xc permissions.user.add`, e);
} }
} else { } else {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.routes.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.routes.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const routes: Route[] = require(file); const routes: Route[] = require(file);
const roles = this.extractUniqueRoles(routes); const roles = this.extractUniqueRoles(routes);
if (roles.includes(user)) { if (roles.includes(user)) {
console.warn(`${user} already exist in ${modelName} policy`); console.warn(`${user} already exist in ${modelName} policy`);
return; return;
@ -405,49 +471,49 @@ class PermissionsMgr {
route.acl[user] = true; route.acl[user] = true;
} }
console.log(
`Adding new role permission for model:${modelName} roles:${user}`
);
console.log(`Adding new role permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports = ${JSON.stringify(
routes,
null,
const policyFileContent = `module.exports = ${JSON.stringify(routes, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.add`, e); console.error(`Error in xc permissions.user.add`, e);
} }
} }
} }
public static async userDelete(args) { public static async userDelete(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file); const filePermissions = require(file);
const roles = this.extractUniqueGqlPolicyRoles(filePermissions); const roles = this.extractUniqueGqlPolicyRoles(filePermissions);
if (!roles.includes(user)) { if (!roles.includes(user)) {
console.warn(`${user} not exist in ${modelName} policy`); console.warn(`${user} not exist in ${modelName} policy`);
return; return;
@ -457,40 +523,44 @@ class PermissionsMgr {
delete roles1[user]; delete roles1[user];
} }
console.log(
`Deleting user permission for model:${modelName} roles:${user}`
);
console.log(`Deleting user permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports = ${JSON.stringify(
filePermissions,
null,
const policyFileContent = `module.exports = ${JSON.stringify(filePermissions, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
} else { } else {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.routes.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.routes.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const routes: Route[] = require(file); const routes: Route[] = require(file);
const roles = this.extractUniqueRoles(routes);
const roles = this.extractUniqueRoles(routes)
if (!roles.includes(user)) { if (!roles.includes(user)) {
console.warn(`${user} not exist in ${modelName} policy`); console.warn(`${user} not exist in ${modelName} policy`);
@ -501,15 +571,17 @@ class PermissionsMgr {
delete route.acl[user]; delete route.acl[user];
} }
console.log(
`Deleting user permission for model:${modelName} roles:${user}`
);
console.log(`Deleting user permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports = ${JSON.stringify(
routes,
null,
const policyFileContent = `module.exports = ${JSON.stringify(routes, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
@ -517,29 +589,31 @@ class PermissionsMgr {
} }
public static async userRename(args) { public static async userRename(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 3) { if (args._.length < 3) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: oldUser, 2: newUser} = args._; const { 1: oldUser, 2: newUser } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file); const filePermissions = require(file);
const roles = this.extractUniqueGqlPolicyRoles(filePermissions); const roles = this.extractUniqueGqlPolicyRoles(filePermissions);
if (!roles.includes(oldUser)) { if (!roles.includes(oldUser)) {
console.warn(`${oldUser} not exist in ${modelName} policy`); console.warn(`${oldUser} not exist in ${modelName} policy`);
return; return;
@ -554,33 +628,40 @@ class PermissionsMgr {
delete roles1[oldUser]; delete roles1[oldUser];
} }
console.log(
console.log(`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`); `Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
const policyFileContent = `module.exports = ${JSON.stringify(filePermissions, null, 2)};\n`; );
fs.writeFileSync(file, policyFileContent) const policyFileContent = `module.exports = ${JSON.stringify(
filePermissions,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
} else { } else {
try { try {
if (args._.length < 3) { if (args._.length < 3) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: oldUser, 2: newUser} = args._; const { 1: oldUser, 2: newUser } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.routes.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.routes.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const routes: Route[] = require(file); const routes: Route[] = require(file);
const roles = this.extractUniqueRoles(routes); const roles = this.extractUniqueRoles(routes);
@ -599,13 +680,16 @@ class PermissionsMgr {
delete route.acl[oldUser]; delete route.acl[oldUser];
} }
console.log(
console.log(`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`); `Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
const policyFileContent = `module.exports = ${JSON.stringify(routes, null, 2)};\n`; );
fs.writeFileSync(file, policyFileContent) const policyFileContent = `module.exports = ${JSON.stringify(
routes,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
@ -613,8 +697,9 @@ class PermissionsMgr {
} }
public static getPolicyPath() { public static getPolicyPath() {
const projectConfig = jsonfile.readFileSync(
const projectConfig = jsonfile.readFileSync(path.join(process.cwd(), 'config.xc.json')); path.join(process.cwd(), 'config.xc.json')
);
return projectConfig.meta.projectType === 'rest' ? 'routers' : 'resolvers'; return projectConfig.meta.projectType === 'rest' ? 'routers' : 'resolvers';
} }
@ -626,14 +711,11 @@ class PermissionsMgr {
private static extractUniqueRoles(routesList: Route[]) { private static extractUniqueRoles(routesList: Route[]) {
const roles = routesList const roles = routesList
.flatMap( .flatMap(route => Object.keys(route.acl))
route => Object.keys(route.acl)
)
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
return roles; return roles;
} }
private static groupRoutes(routes: Route[]): GroupedRoutes { private static groupRoutes(routes: Route[]): GroupedRoutes {
const groupedRoutes: GroupedRoutes = {}; const groupedRoutes: GroupedRoutes = {};
for (const route of routes) { for (const route of routes) {
@ -644,19 +726,22 @@ class PermissionsMgr {
} }
private static sortFiles(file1: string, file2: string): number { private static sortFiles(file1: string, file2: string): number {
return ((file1.indexOf('.bt.') > -1 ? 1 : 0) || (file1.indexOf('.hm.') > -1 ? 2 : 0)) return (
- ((file2.indexOf('.bt.') > -1 ? 1 : 0) || (file2.indexOf('.hm.') > -1 ? 2 : 0)); ((file1.indexOf('.bt.') > -1 ? 1 : 0) ||
(file1.indexOf('.hm.') > -1 ? 2 : 0)) -
((file2.indexOf('.bt.') > -1 ? 1 : 0) ||
(file2.indexOf('.hm.') > -1 ? 2 : 0))
);
} }
} }
export default PermissionsMgr; export default PermissionsMgr;
export interface Route { export interface Route {
type: string; type: string;
path: string; path: string;
acl: { acl: {
[key: string]: boolean [key: string]: boolean;
}; };
} }
@ -668,9 +753,8 @@ export interface GroupedRoutes {
type: string; type: string;
path: string; path: string;
acl: { acl: {
[key: string]: boolean [key: string]: boolean;
};
};
}; };
}
}
} }

537
packages/nc-cli/src/lib/mgr/PermissionsMgrJs.ts

@ -9,28 +9,29 @@ import Util from '../util/Util';
import Table from 'cli-table3'; import Table from 'cli-table3';
class PermissionsMgr { class PermissionsMgr {
public static async set(args) { public static async set(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 4) { if (args._.length < 4) {
console.warn('Invalid arguments for : xc permissions.set') console.warn('Invalid arguments for : xc permissions.set');
return; return;
} }
// @ts-ignore // @ts-ignore
let [_, models, users, ...resolvers] = args._; let [_, models, users, ...resolvers] = args._;
models = models.split('.'); models = models.split('.');
users = users.split('.'); users = users.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
if (models.includes(modelName) || models[0] === '$') { if (models.includes(modelName) || models[0] === '$') {
@ -42,80 +43,92 @@ class PermissionsMgr {
if (users[0] === '$') { if (users[0] === '$') {
for (const [route, rolesObj] of Object.entries(filePermissions)) { for (const [route, rolesObj] of Object.entries(filePermissions)) {
if (resolvers[0] === '$=1') { if (resolvers[0] === '$=1') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = true; obj[role] = true;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} resolver: ${route}`
);
} else if (resolvers[0] === '$=0') { } else if (resolvers[0] === '$=0') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = false; obj[role] = false;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} resolver: ${route}`
);
} else { } else {
resolvers.forEach(permission => { resolvers.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
if (route === permTuple[0]) { if (route === permTuple[0]) {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} , resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} , resolver: ${route}`
);
} }
}) });
} }
} }
} else { } else {
for (const [route, rolesObj] of Object.entries(filePermissions)) { for (const [route, rolesObj] of Object.entries(filePermissions)) {
resolvers.forEach(permission => { resolvers.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
if (route === permTuple[0]) { if (route === permTuple[0]) {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} , resolver: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} , resolver: ${route}`
);
} }
}) });
} }
} }
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; const policyFileContent = `module.exports.permissions = ${JSON.stringify(
fs.writeFileSync(file, policyFileContent) filePermissions,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
} }
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.set`, e); console.error(`Error in xc permissions.set`, e);
} }
} else { } else {
try { try {
if (args._.length < 4) { if (args._.length < 4) {
console.warn('Invalid arguments for : xc permissions.set') console.warn('Invalid arguments for : xc permissions.set');
return; return;
} }
// @ts-ignore // @ts-ignore
let [_, models, users, ...permissions] = args._; let [_, models, users, ...permissions] = args._;
@ -123,29 +136,28 @@ class PermissionsMgr {
users = users.split('.'); users = users.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
if (models.includes(modelName) || models[0] === '$') { if (models.includes(modelName) || models[0] === '$') {
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
if (users[0] === '$') { if (users[0] === '$') {
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap( .flatMap(methods =>
methods => Object.values(methods) Object.values(methods).flatMap(roles1 => Object.keys(roles1))
.flatMap(roles1 => Object.keys(roles1))
) )
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
for (const [route, methods] of Object.entries(filePermissions)) { for (const [route, methods] of Object.entries(filePermissions)) {
if (permissions[0] === '$=1') { if (permissions[0] === '$=1') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = true; obj[role] = true;
@ -153,8 +165,12 @@ class PermissionsMgr {
}, {}); }, {});
for (const [method, rolesObj] of Object.entries(methods)) { for (const [method, rolesObj] of Object.entries(methods)) {
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} method: ${method}=true, route: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} method: ${method}=true, route: ${route}`
);
} }
} else if (permissions[0] === '$=0') { } else if (permissions[0] === '$=0') {
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
@ -162,59 +178,74 @@ class PermissionsMgr {
return obj; return obj;
}, {}); }, {});
for (const [method, rolesObj] of Object.entries(methods)) { for (const [method, rolesObj] of Object.entries(methods)) {
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} method: ${method}=false, route: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} method: ${method}=false, route: ${route}`
);
} }
} else { } else {
permissions.forEach(permission => { permissions.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
const permObj = roles.reduce((obj, role) => { const permObj = roles.reduce((obj, role) => {
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
if (methods[permTuple[0]]) { if (methods[permTuple[0]]) {
Object.assign(methods[permTuple[0]], permObj) Object.assign(methods[permTuple[0]], permObj);
console.log(`Setting Permissions for model:${modelName} roles:${roles.join(', ')} method: ${permTuple[0]}=${val}, route: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${roles.join(
', '
)} method: ${permTuple[0]}=${val}, route: ${route}`
);
} }
}) });
} }
} }
} else { } else {
for (const [route, methods] of Object.entries(filePermissions)) { for (const [route, methods] of Object.entries(filePermissions)) {
permissions.forEach(permission => { permissions.forEach(permission => {
const permTuple = permission.split('=') const permTuple = permission.split('=');
const val = !!(permTuple.length === 1 ? 1 : +permTuple[1] || 0); const val = !!(permTuple.length === 1
? 1
: +permTuple[1] || 0);
const permObj = users.reduce((obj, role) => { const permObj = users.reduce((obj, role) => {
obj[role] = val; obj[role] = val;
return obj; return obj;
}, {}); }, {});
if (methods[permTuple[0]]) { if (methods[permTuple[0]]) {
Object.assign(methods[permTuple[0]], permObj) Object.assign(methods[permTuple[0]], permObj);
console.log(`Setting Permissions for model:${modelName} roles:${users.join(', ')} method: ${permTuple[0]}=${val}, route: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${users.join(
', '
)} method: ${permTuple[0]}=${val}, route: ${route}`
);
} else if (permTuple[0] === '*') { } else if (permTuple[0] === '*') {
for (const [method, rolesObj] of Object.entries(methods)) { for (const [method, rolesObj] of Object.entries(methods)) {
Object.assign(rolesObj, permObj) Object.assign(rolesObj, permObj);
console.log(`Setting Permissions for model:${modelName} roles:${users.join(', ')} method: ${method}=${val}, route: ${route}`); console.log(
`Setting Permissions for model:${modelName} roles:${users.join(
', '
)} method: ${method}=${val}, route: ${route}`
);
} }
} }
}) });
} }
} }
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; const policyFileContent = `module.exports.permissions = ${JSON.stringify(
fs.writeFileSync(file, policyFileContent) filePermissions,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
} }
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.set`, e); console.error(`Error in xc permissions.set`, e);
} }
@ -222,27 +253,30 @@ class PermissionsMgr {
} }
public static async get(args) { public static async get(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.get') console.warn('Invalid arguments for : xc permissions.get');
return; return;
} }
let {1: models} = args._; let { 1: models } = args._;
models = models.split('.'); models = models.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
// instantiate // instantiate
let rows: any[] = []; let rows: any[] = [];
let roles: any[] = []; let roles: any[] = [];
glob.sync(policiesPath).forEach(file => {
glob.sync(policiesPath).forEach((file) => {
// let filePermissions = require(file).permissions; // let filePermissions = require(file).permissions;
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
@ -250,28 +284,27 @@ class PermissionsMgr {
if (models.includes(modelName)) { if (models.includes(modelName)) {
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
roles = Object.values(filePermissions) roles = Object.values(filePermissions)
.flatMap( .flatMap(roles1 => Object.keys(roles1))
roles1 => Object.keys(roles1))
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
rows.push([{ rows.push([
{
colSpan: roles.length + 1, colSpan: roles.length + 1,
content: colors.green(file), content: colors.green(file),
hAlign: 'center' hAlign: 'center'
}]) }
]);
for (const [route, methods] of Object.entries(filePermissions)) { for (const [route, methods] of Object.entries(filePermissions)) {
const row: any[] = [{content: route, vAlign: 'center'}]; const row: any[] = [{ content: route, vAlign: 'center' }];
for (const role of roles) { for (const role of roles) {
row.push(methods[role] ? colors.green('✔') : colors.red('x')); row.push(methods[role] ? colors.green('✔') : colors.red('x'));
} }
rows.push(row) rows.push(row);
} }
} }
}) });
const table = new Table({ const table = new Table({
head: ['Route', ...roles] head: ['Route', ...roles]
@ -279,84 +312,97 @@ class PermissionsMgr {
table.push(...rows); table.push(...rows);
console.log(table.toString()); console.log(table.toString());
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.get`, e); console.error(`Error in xc permissions.get`, e);
} }
} } else {
else {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.get') console.warn('Invalid arguments for : xc permissions.get');
return; return;
} }
let {1:models} = args._; let { 1: models } = args._;
models = models.split('.'); models = models.split('.');
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
// instantiate // instantiate
const table = new Table({ const table = new Table({
head: ['Route', 'Role', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH'] head: ['Route', 'Role', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']
}); });
glob.sync(policiesPath).forEach(file => {
glob.sync(policiesPath).forEach((file) => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
if (models.includes(modelName)) { if (models.includes(modelName)) {
if (models.includes(modelName)) { if (models.includes(modelName)) {
const filePermissions: { readonly [key: string]: any } = require(file).permissions; const filePermissions: {
readonly [key: string]: any;
} = require(file).permissions;
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap( .flatMap(methods =>
methods => Object.values(methods) Object.values(methods).flatMap(roles1 => Object.keys(roles1))
.flatMap(roles1 => Object.keys(roles1))
) )
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
table.push([{ table.push([
{
colSpan: 7, colSpan: 7,
content: colors.green(file), content: colors.green(file),
hAlign: 'center' hAlign: 'center'
}]) }
]);
for (const [route, methods] of Object.entries(filePermissions)) { for (const [route, methods] of Object.entries(filePermissions)) {
let i = 0; let i = 0;
for (const role of roles) { for (const role of roles) {
{ {
table.push([...(i++ ? [] : [{ table.push([
...(i++
? []
: [
{
content: route, content: route,
rowSpan: roles.length, rowSpan: roles.length,
vAlign: 'center' vAlign: 'center'
}]), role, }
methods.get && methods.get[role] ? colors.green('✔') : colors.red('x'), ]),
methods.post && methods.post[role] ? colors.green('✔') : colors.red('x'), role,
methods.put && methods.put[role] ? colors.green('✔') : colors.red('x'), methods.get && methods.get[role]
methods.delete && methods.delete[role] ? colors.green('✔') : colors.red('x'), ? colors.green('✔')
methods.patch && methods.patch[role] ? colors.green('✔') : colors.red('x'), : colors.red('x'),
] as any) methods.post && methods.post[role]
? colors.green('✔')
: colors.red('x'),
methods.put && methods.put[role]
? colors.green('✔')
: colors.red('x'),
methods.delete && methods.delete[role]
? colors.green('✔')
: colors.red('x'),
methods.patch && methods.patch[role]
? colors.green('✔')
: colors.red('x')
] as any);
} }
} }
} }
} }
// console.log(`Model : ${modelName} \n${JSON.stringify(filePermissions, 0, 2)} `) // console.log(`Model : ${modelName} \n${JSON.stringify(filePermissions, 0, 2)} `)
} }
}) });
console.log(table.toString()); console.log(table.toString());
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.get`, e); console.error(`Error in xc permissions.get`, e);
} }
@ -364,32 +410,33 @@ class PermissionsMgr {
} }
public static async userAdd(args) { public static async userAdd(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap(roles1 => Object.keys(roles1)) .flatMap(roles1 => Object.keys(roles1))
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
if (roles.includes(user)) { if (roles.includes(user)) {
console.warn(`${user} already exist in ${modelName} policy`); console.warn(`${user} already exist in ${modelName} policy`);
return; return;
@ -399,47 +446,49 @@ class PermissionsMgr {
roles1[user] = true; roles1[user] = true;
} }
console.log(
`Adding new role permission for model:${modelName} roles:${user}`
);
console.log(`Adding new role permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports.permissions = ${JSON.stringify(
filePermissions,
null,
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.add`, e); console.error(`Error in xc permissions.user.add`, e);
} }
} else { } else {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap( .flatMap(methods =>
methods => Object.values(methods) Object.values(methods).flatMap(roles1 => Object.keys(roles1))
.flatMap(roles1 => Object.keys(roles1))
) )
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
if (roles.includes(user)) { if (roles.includes(user)) {
console.warn(`${user} already exist in ${modelName} policy`); console.warn(`${user} already exist in ${modelName} policy`);
return; return;
@ -451,50 +500,51 @@ class PermissionsMgr {
} }
} }
console.log(
`Adding new role permission for model:${modelName} roles:${user}`
);
console.log(`Adding new role permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports.permissions = ${JSON.stringify(
filePermissions,
null,
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.add`, e); console.error(`Error in xc permissions.user.add`, e);
} }
} }
} }
public static async userDelete(args) { public static async userDelete(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap(roles1 => Object.keys(roles1)) .flatMap(roles1 => Object.keys(roles1))
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
if (!roles.includes(user)) { if (!roles.includes(user)) {
console.warn(`${user} not exist in ${modelName} policy`); console.warn(`${user} not exist in ${modelName} policy`);
return; return;
@ -504,46 +554,49 @@ class PermissionsMgr {
delete roles1[user]; delete roles1[user];
} }
console.log(
`Deleting user permission for model:${modelName} roles:${user}`
);
console.log(`Deleting user permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports.permissions = ${JSON.stringify(
filePermissions,
null,
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
} else { } else {
try { try {
if (args._.length < 2) { if (args._.length < 2) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: user} = args._; const { 1: user } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap( .flatMap(methods =>
methods => Object.values(methods) Object.values(methods).flatMap(roles1 => Object.keys(roles1))
.flatMap(roles1 => Object.keys(roles1))
) )
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
if (!roles.includes(user)) { if (!roles.includes(user)) {
console.warn(`${user} not exist in ${modelName} policy`); console.warn(`${user} not exist in ${modelName} policy`);
return; return;
@ -555,15 +608,17 @@ class PermissionsMgr {
} }
} }
console.log(
`Deleting user permission for model:${modelName} roles:${user}`
);
console.log(`Deleting user permission for model:${modelName} roles:${user}`); const policyFileContent = `module.exports.permissions = ${JSON.stringify(
filePermissions,
null,
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; 2
fs.writeFileSync(file, policyFileContent) )};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
@ -571,31 +626,33 @@ class PermissionsMgr {
} }
public static async userRename(args) { public static async userRename(args) {
if (Util.isProjectGraphql()) { if (Util.isProjectGraphql()) {
try { try {
if (args._.length < 3) { if (args._.length < 3) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: oldUser,2: newUser} = args._; const { 1: oldUser, 2: newUser } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap(roles1 => Object.keys(roles1)) .flatMap(roles1 => Object.keys(roles1))
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
if (!roles.includes(oldUser)) { if (!roles.includes(oldUser)) {
console.warn(`${oldUser} not exist in ${modelName} policy`); console.warn(`${oldUser} not exist in ${modelName} policy`);
return; return;
@ -610,43 +667,48 @@ class PermissionsMgr {
delete roles1[oldUser]; delete roles1[oldUser];
} }
console.log(
console.log(`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`); `Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; );
fs.writeFileSync(file, policyFileContent) const policyFileContent = `module.exports.permissions = ${JSON.stringify(
filePermissions,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
} else { } else {
try { try {
if (args._.length < 3) { if (args._.length < 3) {
console.warn('Invalid arguments for : xc permissions.userAdd') console.warn('Invalid arguments for : xc permissions.userAdd');
return; return;
} }
const {1: oldUser, 2:newUser} = args._; const { 1: oldUser, 2: newUser } = args._;
/* get all policies */ /* get all policies */
const policiesPath = path.join(process.cwd(), 'server', PermissionsMgr.getPolicyPath(), '**', '*.policy.js'); const policiesPath = path.join(
process.cwd(),
glob.sync(policiesPath).forEach((file) => { 'server',
PermissionsMgr.getPolicyPath(),
'**',
'*.policy.js'
);
glob.sync(policiesPath).forEach(file => {
const modelName = path.basename(file).split('.')[0]; const modelName = path.basename(file).split('.')[0];
const filePermissions = require(file).permissions; const filePermissions = require(file).permissions;
const roles = Object.values(filePermissions) const roles = Object.values(filePermissions)
.flatMap( .flatMap(methods =>
methods => Object.values(methods) Object.values(methods).flatMap(roles1 => Object.keys(roles1))
.flatMap(roles1 => Object.keys(roles1))
) )
.filter((v, i, arr) => arr.indexOf(v) === i); .filter((v, i, arr) => arr.indexOf(v) === i);
if (!roles.includes(oldUser)) { if (!roles.includes(oldUser)) {
console.warn(`${oldUser} not exist in ${modelName} policy`); console.warn(`${oldUser} not exist in ${modelName} policy`);
return; return;
@ -663,27 +725,28 @@ class PermissionsMgr {
} }
} }
console.log(
console.log(`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`); `Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
const policyFileContent = `module.exports.permissions = ${JSON.stringify(filePermissions, null, 2)};\n`; );
fs.writeFileSync(file, policyFileContent) const policyFileContent = `module.exports.permissions = ${JSON.stringify(
filePermissions,
null,
2
)};\n`;
fs.writeFileSync(file, policyFileContent);
}); });
} catch (e) { } catch (e) {
console.error(`Error in xc permissions.user.delete`, e); console.error(`Error in xc permissions.user.delete`, e);
} }
} }
} }
public static getPolicyPath() { public static getPolicyPath() {
const projectConfig = jsonfile.readFileSync(
const projectConfig = jsonfile.readFileSync(path.join(process.cwd(), 'config.xc.json')); path.join(process.cwd(), 'config.xc.json')
);
return projectConfig.meta.projectType === 'rest' ? 'routers' : 'resolvers'; return projectConfig.meta.projectType === 'rest' ? 'routers' : 'resolvers';
} }
} }
export default PermissionsMgr; export default PermissionsMgr;

77
packages/nc-cli/src/lib/mgr/SocialMgr.ts

@ -6,41 +6,34 @@ import Locales from '../util/Locales';
import socialShareRules from './cliRules.json'; import socialShareRules from './cliRules.json';
import socialText from './SocialText'; import socialText from './SocialText';
class SocialMgr { class SocialMgr {
public static async share(args) { public static async share(args) {
try { try {
const shareUrl = await SocialMgr.getShareUrl({ const shareUrl = await SocialMgr.getShareUrl({
text: 'A revolutionary API framework with a Desktop App.', text: 'A revolutionary API framework with a Desktop App.',
type: args.type, type: args.type,
url: 'https://NocoDB.com' url: 'https://NocoDB.com'
}); });
open(shareUrl, {wait: true}); open(shareUrl, { wait: true });
} catch (e) { } catch (e) {
console.error(`Error in xc ${args.type}`, e); console.error(`Error in xc ${args.type}`, e);
} }
} }
public static async shareSocial(_args = {}) { public static async shareSocial(_args = {}) {
try { try {
const prompt: any = Locales.getPrompt();
const prompt:any = Locales.getPrompt(); const answer = await inquirer.prompt([
const answer = await inquirer
.prompt([
{ {
choices: prompt.choices, choices: prompt.choices,
message: prompt.message, message: prompt.message,
name: 'media', name: 'media',
type: 'list' type: 'list'
} }
]) ]);
switch (answer.media) { switch (answer.media) {
case 'Next time': case 'Next time':
break; break;
@ -52,10 +45,9 @@ class SocialMgr {
break; break;
case 'Github - ⭐ or 👀 repo': case 'Github - ⭐ or 👀 repo':
open('https://github.com/NocoDB/NocoDB', {wait: true}); open('https://github.com/NocoDB/NocoDB', { wait: true });
break; break;
default: default:
const text = SocialMgr.getShareText(answer.media); const text = SocialMgr.getShareText(answer.media);
// const url = SocialMgr._getShareContentSuffix(answer.media); // const url = SocialMgr._getShareContentSuffix(answer.media);
@ -65,26 +57,21 @@ class SocialMgr {
url: 'https://NocoDB.com' url: 'https://NocoDB.com'
}); });
open(shareUrl, {wait: true}); open(shareUrl, { wait: true });
break; break;
} }
} catch (e) { } catch (e) {
console.error(`Error in xc share`, e); console.error(`Error in xc share`, e);
} }
} }
public static getShareUrl({type, url, text}):any { public static getShareUrl({ type, url, text }): any {
const encUrl = encodeURIComponent(url);
const encUrl = encodeURIComponent(url) const encText = encodeURIComponent(text);
const encText = encodeURIComponent(text)
console.log(__dirname, process.cwd()); console.log(__dirname, process.cwd());
switch (type) { switch (type) {
case 'Twitter': case 'Twitter':
return `https://twitter.com/intent/tweet?url=${encUrl}&text=${encText}&hashtags=xgenecloud`; return `https://twitter.com/intent/tweet?url=${encUrl}&text=${encText}&hashtags=xgenecloud`;
break; break;
@ -134,36 +121,43 @@ class SocialMgr {
break; break;
case 'OKru': case 'OKru':
return `https://connect.ok.ru/dk?st.cmd=WidgetSharePreview&st.shareUrl=${encUrl}` return `https://connect.ok.ru/dk?st.cmd=WidgetSharePreview&st.shareUrl=${encUrl}`;
break; break;
case 'WeChat': case 'WeChat':
return `https://www.addtoany.com/add_to/wechat?linkurl=${encUrl}&linkname=${encText}`; return `https://www.addtoany.com/add_to/wechat?linkurl=${encUrl}&linkname=${encText}`;
break; break;
} }
} }
public static setShareRules(key, value) { public static setShareRules(key, value) {
socialShareRules[key] = value; socialShareRules[key] = value;
fs.writeFileSync(path.join(__dirname, 'cliRules.json'), JSON.stringify(socialShareRules)); fs.writeFileSync(
path.join(__dirname, 'cliRules.json'),
JSON.stringify(socialShareRules)
);
} }
public static setCreatedApis(value) { public static setCreatedApis(value) {
if (socialShareRules.dontPrompt) { return } if (socialShareRules.dontPrompt) {
return;
}
socialShareRules.createdApis = value; socialShareRules.createdApis = value;
socialShareRules.prompt = value; socialShareRules.prompt = value;
fs.writeFileSync(path.join(__dirname, 'cliRules.json'), JSON.stringify(socialShareRules)); fs.writeFileSync(
path.join(__dirname, 'cliRules.json'),
JSON.stringify(socialShareRules)
);
} }
public static async showPrompt() { public static async showPrompt() {
try { try {
if (socialShareRules.createdApis && socialShareRules.prompt && !socialShareRules.dontPrompt) { if (
await SocialMgr.shareSocial() socialShareRules.createdApis &&
socialShareRules.prompt &&
!socialShareRules.dontPrompt
) {
await SocialMgr.shareSocial();
SocialMgr.setShareRules('prompt', false); SocialMgr.setShareRules('prompt', false);
} }
} catch (e) { } catch (e) {
@ -171,15 +165,18 @@ class SocialMgr {
} }
} }
public static getShareText(socialMediaType) { public static getShareText(socialMediaType) {
return SocialMgr._getShareContentPrefix(socialMediaType) + return (
SocialMgr._getShareContentPrefix(socialMediaType) +
SocialMgr._getShareContentMid(socialMediaType) + SocialMgr._getShareContentMid(socialMediaType) +
SocialMgr._getShareContentSuffix(socialMediaType) SocialMgr._getShareContentSuffix(socialMediaType)
);
} }
public static _getShareContentPrefix(_socialMediaType) { public static _getShareContentPrefix(_socialMediaType) {
return socialText.prefix[Math.floor(Math.random() * socialText.prefix.length)]; return socialText.prefix[
Math.floor(Math.random() * socialText.prefix.length)
];
} }
public static _getShareContentMid(_socialMediaType) { public static _getShareContentMid(_socialMediaType) {
@ -187,12 +184,10 @@ class SocialMgr {
} }
public static _getShareContentSuffix(_socialMediaType) { public static _getShareContentSuffix(_socialMediaType) {
return socialText.suffix[Math.floor(Math.random() * socialText.suffix.length)]; return socialText.suffix[
Math.floor(Math.random() * socialText.suffix.length)
];
} }
} }
export default SocialMgr; export default SocialMgr;

19
packages/nc-cli/src/lib/mgr/SocialText.ts

@ -1,5 +1,7 @@
export default { export default {
mid: ['\n@NocoDB - generates instant REST/GraphQL API on any database.\n+ Has GUI based schema migrations!\n+ Built in API-Client and terminal!\n+ Dark theme and much more!\n'], mid: [
'\n@NocoDB - generates instant REST/GraphQL API on any database.\n+ Has GUI based schema migrations!\n+ Built in API-Client and terminal!\n+ Dark theme and much more!\n'
],
prefix: [ prefix: [
'Super slick!', 'Super slick!',
'Very handy!', 'Very handy!',
@ -64,7 +66,6 @@ export default {
'Woah, Extremely Interesting!', 'Woah, Extremely Interesting!',
'Woah, So useful!', 'Woah, So useful!',
'Super slick API Framework!', 'Super slick API Framework!',
'Very handy API Framework!', 'Very handy API Framework!',
'Impressive API Framework!', 'Impressive API Framework!',
@ -86,17 +87,11 @@ export default {
'Extremely Interesting API Framework!', 'Extremely Interesting API Framework!',
'So useful API Framework', 'So useful API Framework',
'Cool Stuff!', 'Cool Stuff!',
'Woha!', 'Woha!',
'I\'m amazed by how well this works!', "I'm amazed by how well this works!",
'I\'m impressed by how well this works!', "I'm impressed by how well this works!"
], ],
suffix: [ suffix: ['https://github.com/nocodb/nocodb', 'www.nocodb.com']
'https://github.com/nocodb/nocodb', };
'www.nocodb.com'
]
}

132
packages/nc-cli/src/lib/mgr/TryMgr.ts

@ -1,10 +1,10 @@
import chalkPipe from 'chalk-pipe'; import chalkPipe from 'chalk-pipe';
import inquirer from 'inquirer'; import inquirer from 'inquirer';
import path from 'path';
import tcpPortUsed from 'tcp-port-used'; import tcpPortUsed from 'tcp-port-used';
import URL from 'url'; import URL from 'url';
import Util from "../util/Util"; import Lang, { STR } from '../util/Lang';
import path from 'path'; import Util from '../util/Util';
import Lang, {STR} from "../util/Lang";
import('colors'); import('colors');
@ -36,12 +36,10 @@ const dbDefaults = {
username: 'sa', username: 'sa',
password: '', password: '',
database: '' database: ''
}, }
}; };
class TryMgr { class TryMgr {
/** /**
* *
* Does the below : * Does the below :
@ -57,22 +55,24 @@ class TryMgr {
let dbUrl; let dbUrl;
if (args._[0] !== 't' && args._[0] !== 'try') { if (args._[0] !== 't' && args._[0] !== 'try') {
if ( args._[1] === 'rest') { if (args._[1] === 'rest') {
dbUrl = `sqlite3://sqlite3?d=${path.join(__dirname, 'sakila.db')}`; dbUrl = `sqlite3://sqlite3?d=${path.join(__dirname, 'sakila.db')}`;
} else if (args._[1] === 'gql') { } else if (args._[1] === 'gql') {
dbUrl = `sqlite3://sqlite3?d=${path.join(__dirname, 'sakila.db')}&api=graphql`; dbUrl = `sqlite3://sqlite3?d=${path.join(
__dirname,
'sakila.db'
)}&api=graphql`;
} }
} else { } else {
/* Construct database URL from prompt */ /* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults); const dbTypes = Object.keys(dbDefaults);
args.url = [] args.url = [];
const finalAnswers = await inquirer const finalAnswers = await inquirer.prompt([
.prompt([
{ {
name: 'type', name: 'type',
type: 'list', type: 'list',
message: Lang.getString(STR.DB_TYPE),// '🔥 Choose SQL Database type\t:', message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({ choices: dbTypes.map(t => ({
name: t, name: t,
value: t, value: t,
@ -86,49 +86,57 @@ class TryMgr {
{ {
name: 'host', name: 'host',
type: 'input', type: 'input',
message: Lang.getString(STR.DB_HOST),// '👉 Enter database host name\t:', message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].host return dbDefaults[ans.type].host;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
name: 'port', name: 'port',
type: 'number', type: 'number',
message: Lang.getString(STR.DB_PORT),// '👉 Enter database port number\t:', message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].port return dbDefaults[ans.type].port;
}, },
transformer(color) { transformer(color) {
try { try {
return color.green.bold; return color.green.bold;
} catch (e) { } catch (e) {
return color return color;
} }
}, },
validate(port, answers) { validate(port, answers) {
const done = this.async(); const done = this.async();
if (answers.host === 'host.docker.internal' || answers.host === 'docker.for.win.localhost') { if (
done(null, true) answers.host === 'host.docker.internal' ||
answers.host === 'docker.for.win.localhost'
) {
done(null, true);
} else { } else {
TryMgr.isPortOpen(answers.host, port).then(isOpen => { TryMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) { if (isOpen) {
done(null, true) done(null, true);
} else { } else {
// done('Port is not open') // done('Port is not open')
console.log(`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`.red.bold) console.log(
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
.red.bold
);
process.exit(0); process.exit(0);
} }
}).catch(done) })
.catch(done);
} }
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -136,13 +144,13 @@ class TryMgr {
type: 'input', type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:', message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) { default(ans) {
return dbDefaults[ans.type].username return dbDefaults[ans.type].username;
}, },
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -151,10 +159,10 @@ class TryMgr {
mask: true, mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:', message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) { transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('') return new Array(color.length).fill('*'.green.bold).join('');
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -164,8 +172,8 @@ class TryMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, },
{ {
@ -180,16 +188,18 @@ class TryMgr {
transformer(color) { transformer(color) {
return chalkPipe(color)(color.green.bold); return chalkPipe(color)(color.green.bold);
}, },
when({type}) { when({ type }) {
return type !== 'sqlite3' return type !== 'sqlite3';
} }
}, }
]) ]);
// console.log(finalAnswers); // console.log(finalAnswers);
if (finalAnswers.type === 'sqlite3') { if (finalAnswers.type === 'sqlite3') {
console.log('Please use desktop app to create Sqlite project'.green.bold) console.log(
'Please use desktop app to create Sqlite project'.green.bold
);
process.exit(0); process.exit(0);
} }
@ -200,7 +210,6 @@ class TryMgr {
}*/ }*/
// //
/* prepare the args */ /* prepare the args */
// const url = `${finalAnswers.type}://${finalAnswers.host}:${finalAnswers.port}?u=${finalAnswers.username}&p=${finalAnswers.password}&d=${finalAnswers.database}&api=${apiTypeMapping[finalAnswers.projectType]}`; // const url = `${finalAnswers.type}://${finalAnswers.host}:${finalAnswers.port}?u=${finalAnswers.username}&p=${finalAnswers.password}&d=${finalAnswers.database}&api=${apiTypeMapping[finalAnswers.projectType]}`;
// args._[0] = finalAnswers.projectType === 'REST APIs' ? 'gar' : 'gag'; // args._[0] = finalAnswers.projectType === 'REST APIs' ? 'gar' : 'gag';
@ -218,16 +227,19 @@ class TryMgr {
finalAnswers.apiType = 'rest'; finalAnswers.apiType = 'rest';
break; break;
} }
dbUrl = `${finalAnswers.type}://${finalAnswers.host}:${finalAnswers.port}?u=${finalAnswers.username}&p=${finalAnswers.password}&d=${finalAnswers.database}&api=${finalAnswers.apiType}` dbUrl = `${finalAnswers.type}://${finalAnswers.host}:${finalAnswers.port}?u=${finalAnswers.username}&p=${finalAnswers.password}&d=${finalAnswers.database}&api=${finalAnswers.apiType}`;
} }
// await Util.runCmd(`cd ${__dirname};echo "const {XcTry} = require('xc-instant'); process.env.NC_DB_URL='${finalAnswers.dbUrl}'; XcTry().then(() => console.log('App started'));" | node`); // await Util.runCmd(`cd ${__dirname};echo "const {XcTry} = require('xc-instant'); process.env.NC_DB_URL='${finalAnswers.dbUrl}'; XcTry().then(() => console.log('App started'));" | node`);
await Util.runCmd(`echo "const {XcTry} = require('xc-instant'); XcTry('${dbUrl}').then(() => console.log('App started'));" | NODE_PATH=${path.join(__dirname, '..', 'node_modules')} node`); await Util.runCmd(
`echo "const {XcTry} = require('xc-instant'); XcTry('${dbUrl}').then(() => console.log('App started'));" | NODE_PATH=${path.join(
__dirname,
'..',
'node_modules'
)} node`
);
} }
public static async testConnection({ url }) {
public static async testConnection({url}) {
for (const u of url) { for (const u of url) {
const parsedUrlData = URL.parse(u, true); const parsedUrlData = URL.parse(u, true);
const queryParams = parsedUrlData.query; const queryParams = parsedUrlData.query;
@ -235,37 +247,41 @@ class TryMgr {
const config = { const config = {
client, client,
connection: { connection: {
database: client === 'pg' ? 'postgres' : (client === 'mssql' ? undefined : null), database:
client === 'pg'
? 'postgres'
: client === 'mssql'
? undefined
: null,
host: parsedUrlData.hostname, host: parsedUrlData.hostname,
password: queryParams.p, password: queryParams.p,
port: +parsedUrlData.port, port: +parsedUrlData.port,
user: queryParams.u, user: queryParams.u
} }
}; };
try { try {
const knex = require('knex')(config) const knex = require('knex')(config);
await knex.raw("SELECT 1+1 as data"); await knex.raw('SELECT 1+1 as data');
} catch (e) { } catch (e) {
console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold) console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold);
return false; return false;
} }
} }
return true; return true;
} }
public static async isPortOpen(host, port) { public static async isPortOpen(host, port) {
try { try {
return await tcpPortUsed.check(+port, host) return await tcpPortUsed.check(+port, host);
} catch (e) { } catch (e) {
console.log(e) console.log(e);
console.log(`\n😩 ${host}:${port} is not reachable please check\n`.red.bold) console.log(
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
);
return true; return true;
} }
} }
} }
export default TryMgr; export default TryMgr;

77
packages/nc-cli/src/lib/mgr/XcInstantMgr.ts

@ -11,11 +11,14 @@ import('colors');
const PROGRESS_WIDTH = 30; const PROGRESS_WIDTH = 30;
class AppMgr { class AppMgr {
public static async install(args) { public static async install(args) {
try { try {
const spinner = ora({text: 'Downloading Desktop App from Github..'.green.bold(), spinner: 'dots2', color: 'green'}).start(); const spinner = ora({
const {src, dest} = await AppMgr.getDownloadLink(args); text: 'Downloading Desktop App from Github..'.green.bold(),
spinner: 'dots2',
color: 'green'
}).start();
const { src, dest } = await AppMgr.getDownloadLink(args);
console.log(`\t${src}`); console.log(`\t${src}`);
@ -23,20 +26,25 @@ class AppMgr {
// console.log(progress) // console.log(progress)
// Report download progress // Report download progress
const p = PROGRESS_WIDTH * progress.percent; const p = PROGRESS_WIDTH * progress.percent;
spinner.text = `Downloading Desktop App now..\n[${ spinner.text = `Downloading Desktop App now..\n[${Array.from(
Array.from({length: PROGRESS_WIDTH}, (_, i) => i <= p ? '=' : ' ').join('') { length: PROGRESS_WIDTH },
}] ${(progress.transferred / (1024 * 1024)).toFixed(2)}MB/${(progress.total / (1024 * 1024)).toFixed(2)}MB\n`.green.bold() (_, i) => (i <= p ? '=' : ' ')
).join('')}] ${(progress.transferred / (1024 * 1024)).toFixed(2)}MB/${(
progress.total /
(1024 * 1024)
).toFixed(2)}MB\n`.green.bold();
}); });
// spinner.prefixText = ''; // spinner.prefixText = '';
spinner.succeed(`Installable downloaded successfully at ./${dest}`.green.bold()); spinner.succeed(
`Installable downloaded successfully at ./${dest}`.green.bold()
);
console.log(`\nInstallable will open automatically now.`.green.bold); console.log(`\nInstallable will open automatically now.`.green.bold);
console.log(`If not, please install it manually.`.green.bold); console.log(`If not, please install it manually.`.green.bold);
if (os.type() === 'Windows_NT') { if (os.type() === 'Windows_NT') {
// open(dest, {wait: true, app: 'explorer.exe'}) // open(dest, {wait: true, app: 'explorer.exe'})
} else { } else {
open(dest, {wait: true}); open(dest, { wait: true });
} }
} catch (e) { } catch (e) {
console.error(`Error in xc app.install`, e); console.error(`Error in xc app.install`, e);
} }
@ -45,7 +53,9 @@ class AppMgr {
public static async open(args) { public static async open(args) {
try { try {
const runCommand = AppMgr.getOpenCommand(args); const runCommand = AppMgr.getOpenCommand(args);
if (!runCommand) { return } if (!runCommand) {
return;
}
if (shell.exec(runCommand).code !== 0) { if (shell.exec(runCommand).code !== 0) {
shell.echo(`\n\nError running command internally`.red); shell.echo(`\n\nError running command internally`.red);
shell.echo(`\nExiting...`.red); shell.echo(`\nExiting...`.red);
@ -56,20 +66,27 @@ class AppMgr {
} }
} }
public static async getDownloadLink(args):Promise<any> { public static async getDownloadLink(args): Promise<any> {
try { try {
let src; let src;
let dest; let dest;
const urls:any = {}; const urls: any = {};
const res = await axios.get('https://api.github.com/repos/xgenecloud/xc-desktop-app/releases?page=1') const res = await axios.get(
'https://api.github.com/repos/xgenecloud/xc-desktop-app/releases?page=1'
);
let status = 0; let status = 0;
for (let i = 0; i < res.data.length && status !== 15; i++) { for (let i = 0; i < res.data.length && status !== 15; i++) {
const assets = res.data[i].assets; const assets = res.data[i].assets;
for (const {name, browser_download_url} of assets) { for (const { name, browser_download_url } of assets) {
switch (name.split('.').pop().toLowerCase()) { switch (
name
.split('.')
.pop()
.toLowerCase()
) {
case 'dmg': case 'dmg':
urls.dmg = urls.dmg || browser_download_url; urls.dmg = urls.dmg || browser_download_url;
status = status | 1; status = status | 1;
@ -92,20 +109,22 @@ class AppMgr {
switch (os.type()) { switch (os.type()) {
case 'Linux': case 'Linux':
const linuxInfo = osInfo({mode: 'sync'}); const linuxInfo = osInfo({ mode: 'sync' });
if (args.debian) { src = urls.deb; } if (args.debian) {
else if (args.rpm) { src = urls.rpm; } src = urls.deb;
else { } else if (args.rpm) {
src = urls.rpm;
} else {
switch (linuxInfo.id) { switch (linuxInfo.id) {
case 'ubuntu': case 'ubuntu':
case 'raspberry': case 'raspberry':
src = urls.deb src = urls.deb;
break; break;
case 'fedora': case 'fedora':
src = urls.rpm src = urls.rpm;
break; break;
default: default:
src = urls.rpm src = urls.rpm;
} }
} }
break; break;
@ -120,22 +139,22 @@ class AppMgr {
} }
dest = src.split('/').pop(); dest = src.split('/').pop();
return {src, dest} return { src, dest };
} catch (e) { } catch (e) {
console.log(e) console.log(e);
} }
} }
public static getOpenCommand(_args):any { public static getOpenCommand(_args): any {
switch (os.type()) { switch (os.type()) {
case 'Linux': case 'Linux':
return 'xgenecloud' return 'xgenecloud';
break; break;
case 'Darwin': case 'Darwin':
return 'open -a xgenecloud' return 'open -a xgenecloud';
break; break;
case 'Windows_NT': case 'Windows_NT':
console.info('Open xgenecloud desktop app from Windows start menu') console.info('Open xgenecloud desktop app from Windows start menu');
break; break;
default: default:
@ -144,6 +163,4 @@ class AppMgr {
} }
} }
export default AppMgr; export default AppMgr;

53
packages/nc-cli/src/lib/prompts/Menu.ts

@ -6,30 +6,23 @@
import inquirer from 'inquirer'; import inquirer from 'inquirer';
class RunOrDownload { class RunOrDownload {
public static async prepareCmd(ipc, args) { public static async prepareCmd(ipc, args) {
args._[0] = ''; args._[0] = '';
const answers = await inquirer.prompt([ const answers = await inquirer.prompt([
{ {
choices: [ choices: ['gen', 'add', 'show', 'run'],
'gen',
'add',
'show',
'run',
],
message: 'What do you want to do?', message: 'What do you want to do?',
name: 'action', name: 'action',
type: 'rawlist' type: 'rawlist'
}]); }
]);
args._[0] = answers.action; args._[0] = answers.action;
switch (answers.action) { switch (answers.action) {
case 'gen': case 'gen':
await this.handleGen(ipc,args) await this.handleGen(ipc, args);
break; break;
case 'add': case 'add':
@ -40,13 +33,10 @@ class RunOrDownload {
case 'run': case 'run':
break; break;
} }
} }
public static async handleGen(_ipc,args) { public static async handleGen(_ipc, args) {
const a1 = await inquirer.prompt([ const a1 = await inquirer.prompt([
{ {
choices: [ choices: [
@ -59,57 +49,42 @@ class RunOrDownload {
'resolver', 'resolver',
'type', 'type',
'schema', 'schema',
'apis', 'apis'
], ],
message: 'What do you want to generate ?', message: 'What do you want to generate ?',
name: 'action', name: 'action',
pageSize: 9, pageSize: 9,
type: 'rawlist' type: 'rawlist'
}]); }
]);
args._[0] += `:${a1.action}`; args._[0] += `:${a1.action}`;
switch (a1.action) { switch (a1.action) {
case 'apis': case 'apis':
const a2 = await inquirer.prompt([ const a2 = await inquirer.prompt([
{ {
choices: [ choices: ['rest', 'graphql'],
'rest',
'graphql'
],
message: 'Which apis you want to use?', message: 'Which apis you want to use?',
name: 'action', name: 'action',
type: 'rawlist' type: 'rawlist'
}]); }
]);
args._[0] += `:${a2.action}`; args._[0] += `:${a2.action}`;
break; break;
} }
} }
// tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty
public static async handleAdd() { public static async handleAdd() {}
}
// tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty
public static async handleShow() { public static async handleShow() {}
}
// tslint:disable-next-line:no-empty // tslint:disable-next-line:no-empty
public static async handleRun() { public static async handleRun() {}
}
} }
export default RunOrDownload; export default RunOrDownload;

20
packages/nc-cli/src/lib/prompts/RunOrDownload.ts

@ -3,18 +3,13 @@
*/ */
'use strict'; 'use strict';
import inquirer from "inquirer"; import inquirer from 'inquirer';
class RunOrDownload { class RunOrDownload {
public static async handle(_args) { public static async handle(_args) {
const answers = await inquirer.prompt([ const answers = await inquirer.prompt([
{ {
choices: [ choices: ['Open the app!', 'Download it for FREE'],
'Open the app!',
'Download it for FREE'
],
message: 'Your XGENE desktop app is not open - do you want to ?', message: 'Your XGENE desktop app is not open - do you want to ?',
name: 'action', name: 'action',
type: 'rawlist' type: 'rawlist'
@ -22,21 +17,16 @@ class RunOrDownload {
]); ]);
switch (answers.action) { switch (answers.action) {
case 'Open app!': case 'Open app!':
break; break;
case 'Download it for FREE': case 'Download it for FREE':
console.log('wget(https://xgene.cloud/download?latest=true) to Downloads'); console.log(
'wget(https://xgene.cloud/download?latest=true) to Downloads'
);
break; break;
} }
} }
} }
export default RunOrDownload; export default RunOrDownload;

23
packages/nc-cli/src/lib/util/Lang.ts

@ -3,15 +3,16 @@ import english from './english.json';
import translated from './translated.json'; import translated from './translated.json';
/* Converted from : https://smodin.me/translate-one-text-into-multiple-languages /* Converted from : https://smodin.me/translate-one-text-into-multiple-languages
* Enter database host name || Choose SQL Database type || Enter database username || Enter database password || Enter database port number || Enter database/schema name || Enter API type to generate || How do you want to run it * Enter database host name || Choose SQL Database type || Enter database username || Enter database password || Enter database port number || Enter database/schema name || Enter API type to generate || How do you want to run it
* */ * */
const formattedTranslate: any = {}; const formattedTranslate: any = {};
for (const {symbol, text} of [english, ...translated].sort((a, b) => a.symbol.localeCompare(b.symbol))) { for (const { symbol, text } of [english, ...translated].sort((a, b) =>
formattedTranslate [symbol] = text.split(/\s*\|\|\s*/); a.symbol.localeCompare(b.symbol)
)) {
formattedTranslate[symbol] = text.split(/\s*\|\|\s*/);
} }
const dummy: any = new Date(); const dummy: any = new Date();
const offset: any = -dummy.getTimezoneOffset(); const offset: any = -dummy.getTimezoneOffset();
const locale: string = offset === 330 ? 'en-IN' : osLocale.sync(); const locale: string = offset === 330 ? 'en-IN' : osLocale.sync();
@ -29,14 +30,10 @@ enum STR {
PROJECT_TYPE PROJECT_TYPE
} }
class Lang { class Lang {
// @ts-ignore // @ts-ignore
public static getString(str: STR) { public static getString(str: STR) {
switch (locale) { switch (locale) {
case 'en': case 'en':
case 'en-GB': case 'en-GB':
case 'en-AU': case 'en-AU':
@ -121,7 +118,6 @@ class Lang {
case 'sv-SE': case 'sv-SE':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.sv?.[str]}\t:`; return `${SMILEY_PREFIX[str]} ${formattedTranslate?.sv?.[str]}\t:`;
case 'th': case 'th':
case 'th-TH': case 'th-TH':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.th?.[str]}\t:`; return `${SMILEY_PREFIX[str]} ${formattedTranslate?.th?.[str]}\t:`;
@ -142,13 +138,8 @@ class Lang {
case 'vi-VN': case 'vi-VN':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.vi?.[str]}\t:`; return `${SMILEY_PREFIX[str]} ${formattedTranslate?.vi?.[str]}\t:`;
} }
} }
} }
export default Lang; export default Lang;
export { export { STR };
STR
};

347
packages/nc-cli/src/lib/util/Locales.ts

@ -1,9 +1,7 @@
import osLocale from 'os-locale'; import osLocale from 'os-locale';
class Locales { class Locales {
public static getPrompt() { public static getPrompt() {
const x = new Date(); const x = new Date();
const offset = -x.getTimezoneOffset(); const offset = -x.getTimezoneOffset();
@ -11,7 +9,6 @@ class Locales {
const locale = offset === 330 ? 'en-IN' : osLocale.sync(); const locale = offset === 330 ? 'en-IN' : osLocale.sync();
switch (locale) { switch (locale) {
case 'en': case 'en':
case 'en-GB': case 'en-GB':
case 'en-AU': case 'en-AU':
@ -20,7 +17,8 @@ class Locales {
case 'en-US': case 'en-US':
default: default:
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
'Facebook', 'Facebook',
@ -29,10 +27,12 @@ class Locales {
'Reddit', 'Reddit',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "English", ],
message: '\n\n👋 Hello! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'English',
} message: '\n\n👋 Hello! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
.green
};
break; break;
case 'zh': case 'zh':
@ -47,17 +47,18 @@ class Locales {
'WeChat', 'WeChat',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'豆瓣', // douban '豆瓣', // douban
'新浪微博',// weibo '新浪微博', // weibo
'Renren', 'Renren',
'Line', 'Line',
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Chinese", ],
message: '\n\n👋 你好! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Chinese',
message: '\n\n👋 你好! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'en-IN': case 'en-IN':
@ -71,14 +72,14 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "English (India)", ],
message: '\n\n👋 Hello / नमस / ನ ಮ ಸ ರ / ന മ സ / வணககம! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'English (India)',
message: '\n\n👋 Hello / नमस / ನ ಮ ಸ ರ / ന മ സ / வணககம! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'de': case 'de':
case 'de-DE': case 'de-DE':
case 'de-CH': case 'de-CH':
@ -94,18 +95,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "German", ],
message: '\n\n👋 Hallo! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'German',
message: '\n\n👋 Hallo! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'el': case 'el':
case 'el-GR': case 'el-GR':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -114,11 +116,12 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Greek", ],
message: '\n\n👋 Γειά σου! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Greek',
message: '\n\n👋 Γειά σου! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'es': case 'es':
@ -134,7 +137,8 @@ class Locales {
case 'es-US': case 'es-US':
case 'es-VE': case 'es-VE':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -143,17 +147,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Spanish", ],
message: '\n\n👋 Hola! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Spanish',
message: '\n\n👋 Hola! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'fa': case 'fa':
case 'fa-IR': case 'fa-IR':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -162,17 +168,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Persian", ],
message: '\n\n👋 سلام! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Persian',
message: '\n\n👋 سلام! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'fi': case 'fi':
case 'fi-FI': case 'fi-FI':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -181,22 +189,22 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Finnish", ],
message: '\n\n👋 سلام! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Finnish',
message: '\n\n👋 سلام! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'fr': case 'fr':
case 'fr-CA': case 'fr-CA':
case 'fr-FR': case 'fr-FR':
case 'fr-BE': case 'fr-BE':
case 'fr-CH': case 'fr-CH':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -205,17 +213,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "French", ],
message: '\n\n👋 Bonjour! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'French',
message: '\n\n👋 Bonjour! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'ga': case 'ga':
case 'ga-IE': case 'ga-IE':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -224,17 +234,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Irish", ],
message: '\n\n👋 Dia dhuit! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Irish',
message: '\n\n👋 Dia dhuit! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'he': case 'he':
case 'he-IL': case 'he-IL':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -243,17 +255,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Hebrew", ],
message: '\n\n👋 שלום! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Hebrew',
message: '\n\n👋 שלום! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'it': case 'it':
case 'it-IT': case 'it-IT':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -262,18 +276,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Italian", ],
message: '\n\n👋 Ciao! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Italian',
message: '\n\n👋 Ciao! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'ja': case 'ja':
case 'ja-JP': case 'ja-JP':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Line', 'Line',
'Linkedin', 'Linkedin',
@ -284,17 +299,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Japanese", ],
message: '\n\n👋 こんにちは! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Japanese',
message: '\n\n👋 こんにちは! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'ko': case 'ko':
case 'ko-KR': case 'ko-KR':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Line', 'Line',
'Linkedin', 'Linkedin',
@ -303,20 +320,22 @@ class Locales {
'WhatsApp', 'WhatsApp',
'WeChat', 'WeChat',
'豆瓣', // douban '豆瓣', // douban
'新浪微博',// weibo '新浪微博', // weibo
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Korean", ],
message: '\n\n👋 여보세요! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Korean',
message: '\n\n👋 여보세요! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'mn-MN': case 'mn-MN':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -324,20 +343,21 @@ class Locales {
'WhatsApp', 'WhatsApp',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Mongolian", ],
message: '\n\n👋 Сайн уу! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Mongolian',
message: '\n\n👋 Сайн уу! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'nl': case 'nl':
case 'nl-BE': case 'nl-BE':
case 'nl-NL': case 'nl-NL':
case 'nn-NO': case 'nn-NO':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -345,19 +365,20 @@ class Locales {
'WhatsApp', 'WhatsApp',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Dutch", ],
message: '\n\n👋 Hallo! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Dutch',
message: '\n\n👋 Hallo! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'pt': case 'pt':
case 'pt-BR': case 'pt-BR':
case 'pt-PT': case 'pt-PT':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -365,17 +386,19 @@ class Locales {
'WhatsApp', 'WhatsApp',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Portuguese", ],
message: '\n\n👋 Olá! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Portuguese',
message: '\n\n👋 Olá! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'ru': case 'ru':
case 'ru-RU': case 'ru-RU':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'OKru', 'OKru',
'Telegram', 'Telegram',
@ -386,18 +409,19 @@ class Locales {
'WhatsApp', 'WhatsApp',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Russian", ],
message: '\n\n👋 Здравствуйте! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Russian',
message: '\n\n👋 Здравствуйте! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'sv': case 'sv':
case 'sv-SE': case 'sv-SE':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -405,18 +429,19 @@ class Locales {
'WhatsApp', 'WhatsApp',
'WeChat', 'WeChat',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Swedish", ],
message: '\n\n👋 Hej! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Swedish',
message: '\n\n👋 Hej! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'th': case 'th':
case 'th-TH': case 'th-TH':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -425,17 +450,19 @@ class Locales {
'Telegram', 'Telegram',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Thai", ],
message: '\n\n👋 สวสด! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Thai',
message: '\n\n👋 สวสด! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'tl': case 'tl':
case 'tl-PH': case 'tl-PH':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -444,18 +471,19 @@ class Locales {
'WeChat', 'WeChat',
'Telegram', 'Telegram',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Filipino", ],
message: '\n\n👋 Kamusta! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Filipino',
message: '\n\n👋 Kamusta! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'tr': case 'tr':
case 'tr-TR': case 'tr-TR':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -463,17 +491,19 @@ class Locales {
'WhatsApp', 'WhatsApp',
'Telegram', 'Telegram',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Turkish", ],
message: '\n\n👋 Merhaba! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Turkish',
message: '\n\n👋 Merhaba! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'uk': case 'uk':
case 'uk-UA': case 'uk-UA':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'OKru', 'OKru',
// 'Reddit', // 'Reddit',
@ -485,17 +515,19 @@ class Locales {
'Wykop', 'Wykop',
'Next time', 'Next time',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Ukrainian", ],
message: '\n\n👋 Здравствуйте! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Ukrainian',
message: '\n\n👋 Здравствуйте! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
case 'vi': case 'vi':
case 'vi-VN': case 'vi-VN':
prompt = { prompt = {
choices: ['Twitter', choices: [
'Twitter',
'Github - ⭐ or 👀 repo', 'Github - ⭐ or 👀 repo',
'Linkedin', 'Linkedin',
// 'Reddit', // 'Reddit',
@ -504,20 +536,17 @@ class Locales {
'WeChat', 'WeChat',
'Telegram', 'Telegram',
'Please dont ask me', 'Please dont ask me',
'- - - - - - - -'], '- - - - - - - -'
language: "Vietnamese", ],
message: '\n\n👋 xin chào! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'.green language: 'Vietnamese',
message: '\n\n👋 xin chào! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
} .green
};
break; break;
} }
return prompt; return prompt;
} }
} }
export default Locales; export default Locales;

301
packages/nc-cli/src/lib/util/Util.ts

@ -2,19 +2,23 @@ import path from 'path';
import shell from 'shelljs'; import shell from 'shelljs';
class Util { class Util {
public static getShortVersion(args) { public static getShortVersion(args) {
const shortVersion = JSON.parse(JSON.stringify(args)); const shortVersion = JSON.parse(JSON.stringify(args));
if (shortVersion._.length) { if (shortVersion._.length) {
shortVersion._[0] = shortVersion._[0].split('.').map(a => a[0]).join('') shortVersion._[0] = shortVersion._[0]
.split('.')
.map(a => a[0])
.join('');
} }
return shortVersion; return shortVersion;
} }
public static isProjectGraphql() { public static isProjectGraphql() {
const currentProjectJson = require(path.join(process.cwd(), 'config.xc.json')) const currentProjectJson = require(path.join(
process.cwd(),
'config.xc.json'
));
return currentProjectJson.meta.projectType.toLowerCase() === 'graphql'; return currentProjectJson.meta.projectType.toLowerCase() === 'graphql';
} }
@ -34,7 +38,9 @@ Commands:
public static manNew() { public static manNew() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc new'.bold} - Creates new projects and creates APIs instantly for database inputted. ${
'xc new'.bold
} - Creates new projects and creates APIs instantly for database inputted.
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc new'.bold} ${'<projectName>'.bold} ${'xc new'.bold} ${'<projectName>'.bold}
@ -54,7 +60,7 @@ ${'VARIATIONS :'.bold}
- Takes in database credentials and API type as input - Takes in database credentials and API type as input
- Database can be new or existing database - Database can be new or existing database
- Creates a new folder by name 'airbnb' - Creates a new folder by name 'airbnb'
` `;
} }
public static manDocker() { public static manDocker() {
@ -77,13 +83,15 @@ ${'VARIATIONS :'.bold}
- Database can be new or existing database - Database can be new or existing database
- Scaffolds REST/GraphQL/gRPC APIs for the database specified - Scaffolds REST/GraphQL/gRPC APIs for the database specified
- These database can be already existing or new databases. - These database can be already existing or new databases.
` `;
} }
public static manGenApisRest() { public static manGenApisRest() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc gen.apis.graphql'.bold} - generates REST APIs for an existing/new databases of a project. ${
'xc gen.apis.graphql'.bold
} - generates REST APIs for an existing/new databases of a project.
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc gen.apis.rest'.bold} [${'-u'.bold} DatabaseURL(s)] ${'xc gen.apis.rest'.bold} [${'-u'.bold} DatabaseURL(s)]
@ -92,38 +100,56 @@ ${'VARIATIONS :'.bold}
The following variations are available: The following variations are available:
${'<>'.bold} If ${'no'.bold} option is passed, this generates REST APIs for databases current project ${'<>'.bold} If ${
'no'.bold
} option is passed, this generates REST APIs for databases current project
that are within project file config.xc.json that are within project file config.xc.json
${'-u'.bold} ${'<Database URLs>'.bold} Creates a new project for an existing/new database ${'-u'.bold} ${
'<Database URLs>'.bold
} Creates a new project for an existing/new database
For mysql : mysql://localhost:3306?u=root&p=password&d=ecommerce For mysql : mysql://localhost:3306?u=root&p=password&d=ecommerce
For pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce For pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce
For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce
${'Examples with notes : '.bold} ${'Examples with notes : '.bold}
${'xc gen.apis.rest -u mysql://localhost:3306?u=root&p=password&d=ecommerce'.bold} ${
'xc gen.apis.rest -u mysql://localhost:3306?u=root&p=password&d=ecommerce'
.bold
}
- Generates REST apis for a mysql database 'ecommerce' - Generates REST apis for a mysql database 'ecommerce'
- Uses current directory as project name - Uses current directory as project name
- If database exists - REST APIs will be created for the tables within it. - If database exists - REST APIs will be created for the tables within it.
- If database doesnt exist - it will be created. - If database doesnt exist - it will be created.
${'xc gen.apis.rest -u pg://localhost:5432?u=postgres&p=password&d=ecommerce'.bold} ${
'xc gen.apis.rest -u pg://localhost:5432?u=postgres&p=password&d=ecommerce'
.bold
}
- Generates REST apis for a postgres database 'ecommerce' - Generates REST apis for a postgres database 'ecommerce'
${'xc gen.apis.rest -u mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce'.bold} ${
'xc gen.apis.rest -u mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce'
.bold
}
- Generates REST apis for a mssql database 'ecommerce' - Generates REST apis for a mssql database 'ecommerce'
${`xc gen.apis.rest -u mysql://localhost:3306?u=root&p=password&d=ecommerce ${
-u pg://localhost:5432?u=postgres&p=password&d=crm`.bold} `xc gen.apis.rest -u mysql://localhost:3306?u=root&p=password&d=ecommerce
-u pg://localhost:5432?u=postgres&p=password&d=crm`
.bold
}
- Generates REST apis for multiple databases 'ecommerce' & 'crm'. - Generates REST apis for multiple databases 'ecommerce' & 'crm'.
- These database can be already existing or new databases. - These database can be already existing or new databases.
` `;
} }
public static manGenApisGraphql() { public static manGenApisGraphql() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc gen.apis.graphql'.bold} - generates GraphQL APIs for an existing/new databases of a project. ${
'xc gen.apis.graphql'.bold
} - generates GraphQL APIs for an existing/new databases of a project.
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc gen.apis.graphql'.bold} [${'-u'.bold} DatabaseURL(s)] ${'xc gen.apis.graphql'.bold} [${'-u'.bold} DatabaseURL(s)]
@ -132,56 +158,84 @@ ${'VARIATIONS :'.bold}
The following variations are available: The following variations are available:
${'<>'.bold} If ${'no'.bold} option is passed, this generates GraphQL APIs for databases current project ${'<>'.bold} If ${
'no'.bold
} option is passed, this generates GraphQL APIs for databases current project
that are within project file config.xc.json that are within project file config.xc.json
${'-u'.bold} ${'<Database URLs>'.bold} Creates a new project for an existing/new database ${'-u'.bold} ${
'<Database URLs>'.bold
} Creates a new project for an existing/new database
For mysql : mysql://localhost:3306?u=root&p=password&d=ecommerce For mysql : mysql://localhost:3306?u=root&p=password&d=ecommerce
For pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce For pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce
For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce
${'Examples with notes : '.bold} ${'Examples with notes : '.bold}
${'xc gen.apis.graphql -u mysql://localhost:3306?u=root&p=password&d=ecommerce'.bold} ${
'xc gen.apis.graphql -u mysql://localhost:3306?u=root&p=password&d=ecommerce'
.bold
}
- Generates GraphQL apis for a mysql database 'ecommerce' - Generates GraphQL apis for a mysql database 'ecommerce'
- Uses current directory as project name - Uses current directory as project name
- If database exists - GraphQL APIs will be created for the tables within it. - If database exists - GraphQL APIs will be created for the tables within it.
- If database doesnt exist - it will be created. - If database doesnt exist - it will be created.
${'xc gen.apis.graphql -u pg://localhost:5432?u=postgres&p=password&d=ecommerce'.bold} ${
'xc gen.apis.graphql -u pg://localhost:5432?u=postgres&p=password&d=ecommerce'
.bold
}
- Generates GraphQL apis for a postgres database 'ecommerce' - Generates GraphQL apis for a postgres database 'ecommerce'
${'xc gen.apis.graphql -u mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce'.bold} ${
'xc gen.apis.graphql -u mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce'
.bold
}
- Generates GraphQL apis for a mssql database 'ecommerce' - Generates GraphQL apis for a mssql database 'ecommerce'
${`xc gen.apis.graphql -u mysql://localhost:3306?u=root&p=password&d=ecommerce ${
-u pg://localhost:5432?u=postgres&p=password&d=crm`.bold} `xc gen.apis.graphql -u mysql://localhost:3306?u=root&p=password&d=ecommerce
-u pg://localhost:5432?u=postgres&p=password&d=crm`
.bold
}
- Generates GraphQL apis for multiple databases 'ecommerce' & 'crm'. - Generates GraphQL apis for multiple databases 'ecommerce' & 'crm'.
- These database can be already existing or new databases. - These database can be already existing or new databases.
` `;
} }
public static manGenModule() { public static manGenModule() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc gen.module'.bold} - Creates a table and scaffolds the respective module files ${
'xc gen.module'.bold
} - Creates a table and scaffolds the respective module files
In REST project - (router, service, middleware, policy, model, meta) In REST project - (router, service, middleware, policy, model, meta)
In GraphQL project - (resolver, service, middleware, policy, model, meta) In GraphQL project - (resolver, service, middleware, policy, model, meta)
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc gen.module'.bold} ${'module(s)'.bold} [--nomodel] [--router] [--service] [--dbAlias] ${'xc gen.module'.bold} ${
'module(s)'.bold
} [--nomodel] [--router] [--service] [--dbAlias]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
The following options are available: The following options are available:
${'--nomodel'.bold} Scaffolds module without creating table and model, meta files. ${
'--nomodel'.bold
} Scaffolds module without creating table and model, meta files.
For mysql : mysql://localhost:3306?u=root&p=password&d=ecommerce For mysql : mysql://localhost:3306?u=root&p=password&d=ecommerce
For pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce For pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce
For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce
${'--dbAlias'.bold} Defaults to 'db'(primary) database if not provided to create the table ${
${'--router'.bold} Will create router with model - service file will be skipped //todo '--dbAlias'.bold
${'--service'.bold} Will create service with model - router file will be skipped //todo } Defaults to 'db'(primary) database if not provided to create the table
${
'--router'.bold
} Will create router with model - service file will be skipped //todo
${
'--service'.bold
} Will create service with model - router file will be skipped //todo
${'VARIATIONS :'.bold} ${'VARIATIONS :'.bold}
@ -206,13 +260,15 @@ ${'VARIATIONS :'.bold}
- All folder/files in respective components will be created in parent table of primary table - All folder/files in respective components will be created in parent table of primary table
` `;
} }
public static manDbMigrateInit() { public static manDbMigrateInit() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc db.migrate.init'.bold} - Initialises a database migration project freshly - only necessary files are created ${
'xc db.migrate.init'.bold
} - Initialises a database migration project freshly - only necessary files are created
- This is a legacy command and will not be required in developer flow - This is a legacy command and will not be required in developer flow
- Instead use ${'xc new'.bold} - Instead use ${'xc new'.bold}
- After running this command - edit config.xc.json and run xc db.migrate.sync - After running this command - edit config.xc.json and run xc db.migrate.sync
@ -228,23 +284,29 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.init --type mysql'.bold} ${'xc db.migrate.init --type mysql'.bold}
- Creates migration project of type mysql - Creates migration project of type mysql
- xc db.migrate.sync has to be run after command - xc db.migrate.sync has to be run after command
` `;
} }
public static manDbMigrateSync() { public static manDbMigrateSync() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc db.migrate.sync'.bold} - Initialises migrations in the databases of project ${
'xc db.migrate.sync'.bold
} - Initialises migrations in the databases of project
- Creates _evolutions table for database if it doesn't exists - Creates _evolutions table for database if it doesn't exists
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc db.migrate.sync'.bold} [${'--env'.bold} <environment>] [${'--dbAlias'.bold} <databaseAlias>] ${'xc db.migrate.sync'.bold} [${'--env'.bold} <environment>] [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
The following options are available: The following options are available:
${'--env'.bold} Defaults to 'dev' environment if not provided ${'--env'.bold} Defaults to 'dev' environment if not provided
${'--dbAlias'.bold} If not provided all databases within environment are initialised ${
'--dbAlias'.bold
} If not provided all databases within environment are initialised
${'VARIATIONS :'.bold} ${'VARIATIONS :'.bold}
@ -259,7 +321,7 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.sync --env production --dbAlias secondary'.bold} ${'xc db.migrate.sync --env production --dbAlias secondary'.bold}
- Initialises migration for 'db2'(secondary) database within 'production' environment - Initialises migration for 'db2'(secondary) database within 'production' environment
` `;
} }
public static manDbMigrateList() { public static manDbMigrateList() {
@ -268,7 +330,9 @@ ${'COMMAND : '.bold}
${'xc db.migrate.list'.bold} - Lists all the migrations ${'xc db.migrate.list'.bold} - Lists all the migrations
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc db.migrate.list'.bold} [${'--env'.bold} <environment>] [${'--dbAlias'.bold} <databaseAlias>] ${'xc db.migrate.list'.bold} [${'--env'.bold} <environment>] [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
@ -290,16 +354,20 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.list --env production --dbAlias secondary'.bold} ${'xc db.migrate.list --env production --dbAlias secondary'.bold}
- Lists all migrations within 'production' environment and 'db2'(secondary) database - Lists all migrations within 'production' environment and 'db2'(secondary) database
` `;
} }
public static manDbMigrateCreate() { public static manDbMigrateCreate() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc db.migrate.create'.bold} - Creates an empty migration for environment and dbAlias ${
'xc db.migrate.create'.bold
} - Creates an empty migration for environment and dbAlias
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc db.migrate.create'.bold} [${'--env'.bold} <environment>] [${'--dbAlias'.bold} <databaseAlias>] ${'xc db.migrate.create'.bold} [${'--env'.bold} <environment>] [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
@ -320,7 +388,7 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.create --env production --dbAlias secondary'.bold} ${'xc db.migrate.create --env production --dbAlias secondary'.bold}
- Creates a migration within 'production' environment and 'db2'(secondary) database - Creates a migration within 'production' environment and 'db2'(secondary) database
` `;
} }
public static manDbMigrateUp() { public static manDbMigrateUp() {
@ -329,7 +397,11 @@ ${'COMMAND : '.bold}
${'xc db.migrate.up'.bold} - Applies all pending migrations ${'xc db.migrate.up'.bold} - Applies all pending migrations
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc db.migrate.up'.bold} [${'--env'.bold} <environment>] [${'--dbAlias'.bold} <databaseAlias>] \n\t\t\t[${'--steps'.bold} <number>] [${'--file'.bold} <number>] ${'xc db.migrate.up'.bold} [${'--env'.bold} <environment>] [${
'--dbAlias'.bold
} <databaseAlias>] \n\t\t\t[${'--steps'.bold} <number>] [${
'--file'.bold
} <number>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
@ -353,18 +425,26 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.up --env production --steps 1'.bold} ${'xc db.migrate.up --env production --steps 1'.bold}
- Applies one pending migrations in 'production' environment - Applies one pending migrations in 'production' environment
${'xc db.migrate.up --env production --dbAlias secondary --steps 1'.bold} ${
'xc db.migrate.up --env production --dbAlias secondary --steps 1'.bold
}
- Applies one pending migrations in 'production' environment for 'db2'(secondary) database - Applies one pending migrations in 'production' environment for 'db2'(secondary) database
` `;
} }
public static manDbMigrateDown() { public static manDbMigrateDown() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc db.migrate.down'.bold} - Reverses all migrations or by steps or by till the filename ${
'xc db.migrate.down'.bold
} - Reverses all migrations or by steps or by till the filename
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc db.migrate.down'.bold} [${'--env'.bold} <environment>] [${'--dbAlias'.bold} <databaseAlias>] \n\t\t\t[${'--steps'.bold} <number>] [${'--file'.bold} <number>] ${'xc db.migrate.down'.bold} [${'--env'.bold} <environment>] [${
'--dbAlias'.bold
} <databaseAlias>] \n\t\t\t[${'--steps'.bold} <number>] [${
'--file'.bold
} <number>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
@ -388,23 +468,29 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.down --env production --steps 1'.bold} ${'xc db.migrate.down --env production --steps 1'.bold}
- Reverses one applied migrations in 'production' environment - Reverses one applied migrations in 'production' environment
${'xc db.migrate.down --env production --dbAlias secondary --steps 1'.bold} ${
'xc db.migrate.down --env production --dbAlias secondary --steps 1'
.bold
}
- Reverses one applied migrations in 'production' environment for 'db2'(secondary) database - Reverses one applied migrations in 'production' environment for 'db2'(secondary) database
` `;
} }
public static manDbMigrateTerm() { public static manDbMigrateTerm() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc db.migrate.term'.bold} - Deprecated. Terminates all databases in environment. ${
` 'xc db.migrate.term'.bold
} - Deprecated. Terminates all databases in environment.
`;
} }
public static manComponentAdd() { public static manComponentAdd() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc component.add'.bold} - Adds a new component in server/components directory by taking user input ${
'xc component.add'.bold
} - Adds a new component in server/components directory by taking user input
on where to place the component in initialisation order. on where to place the component in initialisation order.
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
@ -427,13 +513,15 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold} ${'Examples with notes : '.bold}
${'xc component.add cache'.bold} ${'xc component.add cache'.bold}
- Adds a cache component - Adds a cache component
` `;
} }
public static manAppInstall() { public static manAppInstall() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc app.install'.bold} - Download and starts xgenecloud desktop application installation ${
'xc app.install'.bold
} - Download and starts xgenecloud desktop application installation
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc app.install'.bold} ${'xc app.install'.bold}
@ -449,13 +537,15 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold} ${'Examples with notes : '.bold}
${'xc app.install'.bold} ${'xc app.install'.bold}
` `;
} }
public static manAppOpen() { public static manAppOpen() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc app.open'.bold} - Opens the xgenecloud desktop application (mac and linux only) ${
'xc app.open'.bold
} - Opens the xgenecloud desktop application (mac and linux only)
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc app.open'.bold} ${'xc app.open'.bold}
@ -471,10 +561,9 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold} ${'Examples with notes : '.bold}
${'xc app.open'.bold} ${'xc app.open'.bold}
` `;
} }
public static manPermissionsSet() { public static manPermissionsSet() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
@ -482,17 +571,27 @@ ${'COMMAND : '.bold}
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
# For REST API project # For REST API project
${'xc permissions.set'.bold} [${'model(s)'.bold} | $] [${'userType(s)'.bold} | $] [${'read|write)'.bold} = 1 | 0] ${'xc permissions.set'.bold} [${'model(s)'.bold} | $] [${
'userType(s)'.bold
} | $] [${'read|write)'.bold} = 1 | 0]
# For GraphQL API project # For GraphQL API project
${'xc permissions.set'.bold} [${'model(s)'.bold} | $] [${'userType(s)'.bold} | $] [${'read|write|resolverFunction)'.bold} = 1 | 0] ${'xc permissions.set'.bold} [${'model(s)'.bold} | $] [${
'userType(s)'.bold
} | $] [${'read|write|resolverFunction)'.bold} = 1 | 0]
${'ARGS :'.bold} ${'ARGS :'.bold}
The following are arguments to function: The following are arguments to function:
${'model(s)'.bold} Model name | Multiple models with dot seperated | $ - means all models ${
${'userType(s)'.bold}User role name | Multiple user role names with dot separated | $ - means all user models 'model(s)'.bold
${'permissions(s)'.bold}Permissions - read | write | get | post | put | delete | patch | resolverFunc | $ - means all permissions } Model name | Multiple models with dot seperated | $ - means all models
${
'userType(s)'.bold
}User role name | Multiple user role names with dot separated | $ - means all user models
${
'permissions(s)'.bold
}Permissions - read | write | get | post | put | delete | patch | resolverFunc | $ - means all permissions
${'VARIATIONS :'.bold} ${'VARIATIONS :'.bold}
None None
@ -509,7 +608,7 @@ ${'VARIATIONS :'.bold}
${'xc permissions.set $ $ read=1 write=1'.bold} ${'xc permissions.set $ $ read=1 write=1'.bold}
- For 'all' models 'all' user types SET 'read' and 'write' permission - For 'all' models 'all' user types SET 'read' and 'write' permission
` `;
} }
// todo // todo
@ -536,10 +635,9 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold} ${'Examples with notes : '.bold}
${'xc permissions.get blog'.bold} ${'xc permissions.get blog'.bold}
- Get all permissions of blog model ` - Get all permissions of blog model `;
} }
public static manPermissionsUserAdd() { public static manPermissionsUserAdd() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
@ -564,10 +662,9 @@ ${'VARIATIONS :'.bold}
${'xc permissions.role.add manager'.bold} ${'xc permissions.role.add manager'.bold}
- Adds user role 'manager' to all the models - Adds user role 'manager' to all the models
` `;
} }
public static manPermissionsUserDelete() { public static manPermissionsUserDelete() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
@ -590,10 +687,9 @@ ${'VARIATIONS :'.bold}
${'xc permissions.role.delete manager'.bold} ${'xc permissions.role.delete manager'.bold}
- deletes user role 'manager' from all the models - deletes user role 'manager' from all the models
` `;
} }
public static manPermissionsUserRename() { public static manPermissionsUserRename() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
@ -617,23 +713,28 @@ ${'VARIATIONS :'.bold}
${'xc permissions.role.rename manager StaffManager'.bold} ${'xc permissions.role.rename manager StaffManager'.bold}
- Renames user role from 'manager' to 'StaffManager' in all the models - Renames user role from 'manager' to 'StaffManager' in all the models
` `;
} }
public static manProjectMetaExport() { public static manProjectMetaExport() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc meta.export'.bold} - Exports all meta table data to project meta directory ${
'xc meta.export'.bold
} - Exports all meta table data to project meta directory
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc meta.export'.bold} ${'--env'.bold} <environment> [${'--dbAlias'.bold} <databaseAlias>] ${'xc meta.export'.bold} ${'--env'.bold} <environment> [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
The following options are available: The following options are available:
${'--env'.bold} Environment name to be exported ${'--env'.bold} Environment name to be exported
${'--dbAlias'.bold} dbAlias of database connection. If not provided then it will export metadata for all connections in the environment ${
'--dbAlias'.bold
} dbAlias of database connection. If not provided then it will export metadata for all connections in the environment
${'VARIATIONS :'.bold} ${'VARIATIONS :'.bold}
@ -645,8 +746,7 @@ ${'VARIATIONS :'.bold}
${'xc meta.export --env production --dbAlias db2'.bold} ${'xc meta.export --env production --dbAlias db2'.bold}
- Exports metadata for 'db2' database in 'production' environment - Exports metadata for 'db2' database in 'production' environment
` `;
} }
public static manProjectMetaReset() { public static manProjectMetaReset() {
@ -655,13 +755,17 @@ ${'COMMAND : '.bold}
${'xc meta.reset'.bold} - Clears all meta table data ${'xc meta.reset'.bold} - Clears all meta table data
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc meta.reset'.bold} ${'--env'.bold} <environment> [${'--dbAlias'.bold} <databaseAlias>] ${'xc meta.reset'.bold} ${'--env'.bold} <environment> [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
The following options are available: The following options are available:
${'--env'.bold} Environment name to be reset ${'--env'.bold} Environment name to be reset
${'--dbAlias'.bold} dbAlias of database connection. If not provided then it will clear metadata for all connections in the environment ${
'--dbAlias'.bold
} dbAlias of database connection. If not provided then it will clear metadata for all connections in the environment
${'VARIATIONS :'.bold} ${'VARIATIONS :'.bold}
@ -673,23 +777,28 @@ ${'VARIATIONS :'.bold}
${'xc meta.reset --env production --dbAlias db2'.bold} ${'xc meta.reset --env production --dbAlias db2'.bold}
- Clears metadata for 'db2' database in 'production' environment - Clears metadata for 'db2' database in 'production' environment
` `;
} }
public static manProjectMetaImport() { public static manProjectMetaImport() {
return ` return `
${'COMMAND : '.bold} ${'COMMAND : '.bold}
${'xc meta.import'.bold} - Imports data from project meta folder to meta tables ${
'xc meta.import'.bold
} - Imports data from project meta folder to meta tables
${'SYNOPSIS : '.bold} ${'SYNOPSIS : '.bold}
${'xc meta.import'.bold} ${'--env'.bold} <environment> [${'--dbAlias'.bold} <databaseAlias>] ${'xc meta.import'.bold} ${'--env'.bold} <environment> [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold} ${'OPTIONS :'.bold}
The following options are available: The following options are available:
${'--env'.bold} Environment name to be imported ${'--env'.bold} Environment name to be imported
${'--dbAlias'.bold} dbAlias of database connection. If not provided then it will import metadata to all connections in the environment ${
'--dbAlias'.bold
} dbAlias of database connection. If not provided then it will import metadata to all connections in the environment
${'VARIATIONS :'.bold} ${'VARIATIONS :'.bold}
@ -701,18 +810,13 @@ ${'VARIATIONS :'.bold}
${'xc meta.import --env production --dbAlias db2'.bold} ${'xc meta.import --env production --dbAlias db2'.bold}
- Imports metadata for 'db2' database in 'production' environment - Imports metadata for 'db2' database in 'production' environment
` `;
} }
public static showHelpForCommand(args) { public static showHelpForCommand(args) {
try { try {
switch (args._[1]) { switch (args._[1]) {
case 'new':
case 'new' :
console.log(Util.manNew()); console.log(Util.manNew());
break; break;
@ -870,14 +974,12 @@ ${'VARIATIONS :'.bold}
// //
// /**************** END : Docker ****************/ // /**************** END : Docker ****************/
default: default:
break; break;
} }
} catch (e) { } catch (e) {
throw e; throw e;
} }
} }
public static async runCmd(str) { public static async runCmd(str) {
@ -891,24 +993,17 @@ ${'VARIATIONS :'.bold}
public static escapeShellArg(cmd) { public static escapeShellArg(cmd) {
return '"' + cmd.replace(/(["'$`\\])/g, '\\$1') + '"'; return '"' + cmd.replace(/(["'$`\\])/g, '\\$1') + '"';
}; }
public async play(sound) { public async play(sound) {
switch (sound) { switch (sound) {
case -1: case -1:
break; break;
case 'fun': case 'fun':
break; break;
} }
} }
} }
export default Util; export default Util;

5
packages/nc-cli/src/lib/util/config.ts

@ -1,4 +1,3 @@
export default { export default {
port: 23917, port: 23917
} };

Loading…
Cancel
Save