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. 79
      packages/nc-cli/src/lib/mgr/AppMgr.ts
  4. 49
      packages/nc-cli/src/lib/mgr/Client.ts
  5. 38
      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. 52
      packages/nc-cli/src/lib/mgr/MigrationMgr.ts
  9. 44
      packages/nc-cli/src/lib/mgr/ModelMgr.ts
  10. 782
      packages/nc-cli/src/lib/mgr/NewMgr.ts
  11. 306
      packages/nc-cli/src/lib/mgr/OldNewMgr.ts
  12. 534
      packages/nc-cli/src/lib/mgr/PermissionsMgr.ts
  13. 555
      packages/nc-cli/src/lib/mgr/PermissionsMgrJs.ts
  14. 93
      packages/nc-cli/src/lib/mgr/SocialMgr.ts
  15. 19
      packages/nc-cli/src/lib/mgr/SocialText.ts
  16. 280
      packages/nc-cli/src/lib/mgr/TryMgr.ts
  17. 79
      packages/nc-cli/src/lib/mgr/XcInstantMgr.ts
  18. 55
      packages/nc-cli/src/lib/prompts/Menu.ts
  19. 32
      packages/nc-cli/src/lib/prompts/RunOrDownload.ts
  20. 31
      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';
// tslint:disable-next-line:no-var-requires
const pkg = require('../package.json');
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 */
const args = yargs
.alias('u', 'url')
.alias('m', 'module')
.alias('n', 'nomodel')
.help('help')
.argv;
.help('help').argv;
/* cwd is reference to all commands */
args.folder = process.cwd();
/* handle command */
(async () => {
// Checks for available update and returns an instance
const notifier = updateNotifier({ pkg });
// Checks for available update and returns an instance
const notifier = updateNotifier({pkg});
// Notify using the built-in convenience method
// Notify using the built-in convenience method
notifier.notify();
if (args._) {
if (!args._.length) {
await SocialMgr.showPrompt();
args._.unshift(uniqueNamesGenerator({
dictionaries: [[starWars], [adjectives, animals]][Math.floor(Math.random() * 2)]
}).toLowerCase().replace(/[ -]/g, '_'));
args._.unshift(
uniqueNamesGenerator({
dictionaries: [[starWars], [adjectives, animals]][
Math.floor(Math.random() * 2)
]
})
.toLowerCase()
.replace(/[ -]/g, '_')
);
}
await CliMgr.process(args);
} else {
Util.showHelp(args);
process.exit(0)
process.exit(0);
}
})().catch(err => {
console.error('\n\nThere was an error processing command:');
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 SocialMgr from './mgr/SocialMgr';
// import DockerMgr from "./mgr/DockerMgr";
import NewMgr from "./mgr/NewMgr";
import NewMgr from './mgr/NewMgr';
// import TryMgr from "./mgr/TryMgr";
let cmdProcessedOnce = 0;
let cmdOriginalArgs = null;
class CliMgr {
public static async runCmd(str) {
shell.echo(`\nNow, executing command : ${str}\n\n`.blue);
if (shell.exec(str).code !== 0) {
@ -30,13 +29,11 @@ class CliMgr {
}
public static async process(args) {
cmdOriginalArgs = cmdOriginalArgs ? cmdOriginalArgs : args;
try {
if (args._ && args._.length) {
switch (args._[0]) {
case 'man':
if (args._.length > 1) {
Util.showHelpForCommand(args);
@ -53,11 +50,11 @@ class CliMgr {
if (await NewMgr.getNewProjectInput(args)) {
if (args._[0] === 'gap') {
console.log('gRPC code generation is not yet supported.');
process.exit(0)
process.exit(0);
}
await client.requestSend(args)
await client.requestSend(args);
} else {
process.exit(0)
process.exit(0);
}
break;
@ -405,7 +402,6 @@ class CliMgr {
// process.exit(0)
// break;
default:
if (!cmdProcessedOnce) {
cmdProcessedOnce = 1;
@ -413,9 +409,11 @@ class CliMgr {
args._.unshift('new');
await this.process(args);
} else {
console.log(`\nUnknown command. ${cmdOriginalArgs._[0]} -- please see help below`);
console.log(
`\nUnknown command. ${cmdOriginalArgs._[0]} -- please see help below`
);
Util.showHelp(cmdOriginalArgs);
process.exit(0)
process.exit(0);
}
break;
}
@ -427,4 +425,3 @@ class CliMgr {
}
export default CliMgr;

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

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

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

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

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

@ -2,36 +2,30 @@ import inquirer from 'inquirer';
import path from 'path';
class ComponentMgr {
public static async add(_args) {
const components = require(path.join(process.cwd(), './server/app.components.js'))
const answer = await inquirer
.prompt([
{
choices: components.components.map(component => component.title),
message: 'Choose after which component should we insert the new component?',
name: 'compoonent',
type: 'list'
}
])
const components = require(path.join(
process.cwd(),
'./server/app.components.js'
));
const answer = await inquirer.prompt([
{
choices: components.components.map(component => component.title),
message:
'Choose after which component should we insert the new component?',
name: 'compoonent',
type: 'list'
}
]);
return answer.compoonent;
}
// tslint:disable-next-line:no-empty
public static async rename(_args) {
}
public static async rename(_args) {}
// tslint:disable-next-line:no-empty
public static async delete(_args) {
}
public static async delete(_args) {}
}
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 fs from 'fs';
import path from 'path';
class DockerMgr extends NewMgr {
public static async genDockerfile(args: any) {
const dockerFilePath = path.join(process.cwd(), 'Dockerfile');
try {
args._.push('placeholder')
if(await this.getNewProjectInput(args)) {
args._.push('placeholder');
if (await this.getNewProjectInput(args)) {
const dockerfileContent = this.getDockerfileContent(args);
fs.writeFileSync(dockerFilePath, dockerfileContent);
console.log(`Docker file created successfully`.green.bold)
console.log(`\tFile location : ${dockerFilePath}`.green)
console.log(`\tdocker build . -t xc`.green.bold)
}else{
console.log(`Docker file created successfully`.green.bold);
console.log(`\tFile location : ${dockerFilePath}`.green);
console.log(`\tdocker build . -t xc`.green.bold);
} else {
// console.log('Database connection failed')
}
} catch (e) {
@ -31,14 +29,12 @@ class DockerMgr extends NewMgr {
ENV PORT 8080
ENV NODE_ENV=dev
ENV TOOL_DIR=/tool
${
args.url.map((url, i) => `ENV DB_URL${i > 0 ? i + 1 : ''}=${url}`).join('\r\n')
}
${args.url
.map((url, i) => `ENV DB_URL${i > 0 ? i + 1 : ''}=${url}`)
.join('\r\n')}
`
`;
}
}
export default DockerMgr;

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

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

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

@ -1,15 +1,14 @@
import {Migrator} from 'xc-migrator-ts';
const migrator = new Migrator()
import { Migrator } from 'xc-migrator-ts';
const migrator = new Migrator();
class MigrationMgr {
public static _getFolder(args) {
args.folder = args.folder || process.cwd();
}
public static async init(args) {
try {
args.type = args.type || "mysql";
args.type = args.type || 'mysql';
await migrator.init(args);
} catch (e) {
console.log('db.migrate.init : Error occured', e);
@ -27,9 +26,9 @@ class MigrationMgr {
public static async create(args) {
try {
this._getFolder(args)
this._getFolder(args);
await migrator.migrationsCreate({
dbAlias: args.dbAlias || "primary",
dbAlias: args.dbAlias || 'primary',
folder: args.folder
});
} catch (e) {
@ -38,10 +37,8 @@ class MigrationMgr {
}
public static async up(args) {
try {
this._getFolder(args)
this._getFolder(args);
let migrationSteps = args.steps || 9999;
@ -49,27 +46,24 @@ class MigrationMgr {
migrationSteps = 0;
}
const migratorInst = new Migrator()
const migratorInst = new Migrator();
await migratorInst.migrationsUp({
dbAlias: args.dbAlias || "primary",
env: args.env || "dev",
dbAlias: args.dbAlias || 'primary',
env: args.env || 'dev',
file: args.file || null,
folder: args.folder,
migrationSteps,
onlyList: args.list,
sqlContentMigrate: (+args.sqlContentMigrate === 0 ? 0 : 1)
sqlContentMigrate: +args.sqlContentMigrate === 0 ? 0 : 1
});
} catch (e) {
console.log('db.migrate.up : Error occured', e);
}
}
public static async down(args) {
try {
this._getFolder(args)
this._getFolder(args);
let migrationSteps = args.steps || 9999;
@ -78,25 +72,22 @@ class MigrationMgr {
}
await migrator.migrationsDown({
dbAlias: args.dbAlias || "primary",
env: args.env || "dev",
dbAlias: args.dbAlias || 'primary',
env: args.env || 'dev',
file: args.file || null,
folder: args.folder,
migrationSteps,
onlyList: args.list,
sqlContentMigrate: (+args.sqlContentMigrate === 0 ? 0 : 1)
sqlContentMigrate: +args.sqlContentMigrate === 0 ? 0 : 1
});
} catch (e) {
console.log('db.migrate.down : Error occured', e);
}
}
public static async list(args) {
try {
this._getFolder(args)
this._getFolder(args);
let migrationSteps = args.steps || 9999;
@ -105,8 +96,8 @@ class MigrationMgr {
}
const data = await migrator.migrationsUp({
dbAlias: args.dbAlias || "primary",
env: args.env || "dev",
dbAlias: args.dbAlias || 'primary',
env: args.env || 'dev',
file: args.file || null,
folder: args.folder,
migrationSteps,
@ -114,25 +105,20 @@ class MigrationMgr {
});
console.log(data.data.object.list);
} catch (e) {
console.log('db.migrate.up : Error occured', e);
}
}
public static async clean(args) {
try {
args.type = args.type || "mysql";
args.type = args.type || 'mysql';
await migrator.clean(args);
} catch (e) {
console.log('db.migrate.clean : Error occured', e);
}
}
}
// 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';
class ModelMgr {
/***
*
* @param args
@ -18,25 +16,43 @@ class ModelMgr {
args.dbAlias = args.dbAlias || '*';
if (args.models) {
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`))) {
await fsExtra.remove(file)
console.log(`Removed successfully : ${path.basename(file)}`.green.bold)
for (const file of glob.sync(
path.join(
args.folder,
'server',
'models',
args.dbAlias,
model,
`${model}.meta.*.js`
)
)) {
await fsExtra.remove(file);
console.log(
`Removed successfully : ${path.basename(file)}`.green.bold
);
}
}
} else {
for (const file of glob.sync(path.join(args.folder, 'server', 'models', args.dbAlias, '*', '*.meta.*.js'))) {
await fsExtra.remove(file)
console.log(`Removed successfully : ${path.basename(file)}`.green.bold)
for (const file of glob.sync(
path.join(
args.folder,
'server',
'models',
args.dbAlias,
'*',
'*.meta.*.js'
)
)) {
await fsExtra.remove(file);
console.log(
`Removed successfully : ${path.basename(file)}`.green.bold
);
}
}
}catch (e) {
console.log(`Error while removing backup file`.red.bold)
} catch (e) {
console.log(`Error while removing backup file`.red.bold);
}
}
}
export default ModelMgr;

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

@ -5,14 +5,14 @@ import mkdirp from 'mkdirp';
import path from 'path';
import tcpPortUsed from 'tcp-port-used';
import URL from 'url';
import {promisify} from "util";
import Util from "../util/Util";
import { promisify } from 'util';
import Util from '../util/Util';
import {v4 as uuidv4} from 'uuid';
import * as fs from "fs";
import Lang, {STR} from "../util/Lang";
import boxen from 'boxen';
import * as fs from 'fs';
import os from 'os';
import boxen from "boxen";
import { v4 as uuidv4 } from 'uuid';
import Lang, { STR } from '../util/Lang';
// @ts-ignore
const colors = require('colors');
@ -45,7 +45,7 @@ const dbDefaults = {
username: 'sa',
password: '',
database: ''
},
}
};
// const apiTypeMapping = {
@ -58,9 +58,7 @@ const dbDefaults = {
// 'Typescript': 'ts',
// }
class NewMgr {
/**
*
* Does the below :
@ -73,143 +71,158 @@ class NewMgr {
* @returns {Promise<string|string|boolean|*>}
*/
public static async getNewProjectInput(args): Promise<any> {
if (args._.length < 2) {
const usage = '\n$ xc new project_name'.green.bold
console.log(`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red.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
);
return false;
}
/* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults);
args.url = []
console.log(`NocoDB requires a database to store metadata of database-spreadsheets.\nPlease enter the database credentials (defaults to SQLite3)`.green.bold)
const answers = await inquirer
.prompt([
{
name: 'type',
type: 'list',
message: Lang.getString(STR.DB_TYPE),// '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'sqlite3',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
args.url = [];
console.log(
`NocoDB requires a database to store metadata of database-spreadsheets.\nPlease enter the database credentials (defaults to SQLite3)`
.green.bold
);
const answers = await inquirer.prompt([
{
name: 'type',
type: 'list',
message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'sqlite3',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
},
{
name: 'host',
type: 'input',
message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host;
},
{
name: 'host',
type: 'input',
message: Lang.getString(STR.DB_HOST),// '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'port',
type: 'number',
message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port;
},
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color;
}
},
{
name: 'port',
type: 'number',
message: Lang.getString(STR.DB_PORT),// '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port
},
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color
}
},
validate(port, answers) {
const done = this.async();
if (answers.host === 'host.docker.internal' || answers.host === 'docker.for.win.localhost') {
done(null, true)
} else {
NewMgr.isPortOpen(answers.host, port).then(isOpen => {
validate(port, answers) {
const done = this.async();
if (
answers.host === 'host.docker.internal' ||
answers.host === 'docker.for.win.localhost'
) {
done(null, true);
} else {
NewMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) {
done(null, true)
done(null, true);
} else {
// 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);
}
}).catch(done)
}
},
when({type}) {
return type !== 'sqlite3'
})
.catch(done);
}
},
{
name: 'username',
type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'username',
type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username;
},
{
name: 'password',
type: 'input',
mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('')
},
when({type}) {
return type !== 'sqlite3'
}
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
{
name: 'database',
type: 'input',
default(_ans) {
return args._[1] + '_dev';
},
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'password',
type: 'input',
mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('');
},
{
name: 'projectType',
type: 'list',
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)'
].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'database',
type: 'input',
default(_ans) {
return args._[1] + '_dev';
},
])
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'projectType',
type: 'list',
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)'
].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
}
]);
/* if not valid retry getting right input */
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);
}
@ -226,230 +239,270 @@ class NewMgr {
}
if (answers.projectType === 'mvc' && !answers.isForExisting) {
/* attach new project name to path and 'cd' to that folder */
args.folder = path.join(args.folder, args._[1]);
mkdirp.sync(args.folder);
process.chdir(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') {
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') {
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',
borderStyle: 'round',
margin: 1,
padding: 1
} as any));
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',
borderStyle: 'round',
margin: 1,
padding: 1
} as any
)
);
} else {
await Util.runCmd(`npm install; npm run start;`);
}
} else if (answers.projectType) {
let env = '';
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' : '';
if (os.type() === 'Windows_NT') {
// 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`, {
borderColor: 'green',
borderStyle: 'round',
margin: 1,
padding: 1
} as any));
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',
borderStyle: 'round',
margin: 1,
padding: 1
} as any
)
);
} 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> {
if (args._.length < 2) {
const usage = '\n$ xc new project_name'.green.bold
console.log(`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red.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
);
return false;
}
/* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults);
args.url = []
const answers = await inquirer
.prompt([
{
name: 'type',
type: 'list',
message: Lang.getString(STR.DB_TYPE),// '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'mysql2',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
args.url = [];
const answers = await inquirer.prompt([
{
name: 'type',
type: 'list',
message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'mysql2',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
},
{
name: 'host',
type: 'input',
message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host;
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'port',
type: 'number',
message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port;
},
{
name: 'host',
type: 'input',
message: Lang.getString(STR.DB_HOST),// '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color;
}
},
{
name: 'port',
type: 'number',
message: Lang.getString(STR.DB_PORT),// '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port
},
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color
}
},
validate(port, answers) {
const done = this.async();
if (answers.host === 'host.docker.internal' || answers.host === 'docker.for.win.localhost') {
done(null, true)
} else {
NewMgr.isPortOpen(answers.host, port).then(isOpen => {
validate(port, answers) {
const done = this.async();
if (
answers.host === 'host.docker.internal' ||
answers.host === 'docker.for.win.localhost'
) {
done(null, true);
} else {
NewMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) {
done(null, true)
done(null, true);
} else {
// 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);
}
}).catch(done)
}
},
when({type}) {
return type !== 'sqlite3'
})
.catch(done);
}
},
{
name: 'username',
type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'username',
type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username;
},
{
name: 'password',
type: 'input',
mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('')
},
when({type}) {
return type !== 'sqlite3'
}
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
{
name: 'database',
type: 'input',
default(_ans) {
return args._[1] + '_dev';
},
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'password',
type: 'input',
mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('');
},
{
name: 'apiType',
type: 'list',
message: Lang.getString(STR.DB_API), // '🚀 Enter API type to generate\t:',
choices: ['REST APIs', 'GRAPHQL APIs', 'gRPC APIs'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'database',
type: 'input',
default(_ans) {
return args._[1] + '_dev';
},
{
name: 'projectType',
type: 'list',
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 => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'apiType',
type: 'list',
message: Lang.getString(STR.DB_API), // '🚀 Enter API type to generate\t:',
choices: ['REST APIs', 'GRAPHQL APIs', 'gRPC APIs'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
// {
// name: 'programmingLanguage',
// type: 'list',
// message: '🚀 Enter preferred programming language\t:',
// choices: ['Javascript', 'Typescript'].map(t => ({
// name: t,
// value: t,
// short: t.green.bold
// })),
// transformer(color) {
// return chalkPipe(color)(color.green.bold);
// },
// when({type}) {
// return type !== 'sqlite3'
// }
// }
])
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'projectType',
type: 'list',
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 => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
}
// {
// name: 'programmingLanguage',
// type: 'list',
// message: '🚀 Enter preferred programming language\t:',
// choices: ['Javascript', 'Typescript'].map(t => ({
// name: t,
// value: t,
// short: t.green.bold
// })),
// transformer(color) {
// return chalkPipe(color)(color.green.bold);
// },
// when({type}) {
// return type !== 'sqlite3'
// }
// }
]);
// console.log(answers);
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);
}
/* if not valid retry getting right input */
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);
}
//
/* prepare the args */
// 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';
@ -485,7 +538,6 @@ class NewMgr {
}
if (answers.projectType === 'mvc' && !answers.isForExisting) {
/* attach new project name to path and 'cd' to that folder */
args.folder = path.join(args.folder, args._[1]);
mkdirp.sync(args.folder);
@ -495,72 +547,73 @@ class NewMgr {
await promisify(download)('gitlab:xc-public/test10', args.folder);
const config = {
title: args._[1],
"version": "0.6",
"envs": {
"dev": {
"db": [
version: '0.6',
envs: {
dev: {
db: [
{
"client": answers.type,
"connection": {
"host": answers.host,
"port": answers.port,
"user": answers.username,
"password": answers.password,
"database": answers.database,
"multipleStatements": true
client: answers.type,
connection: {
host: answers.host,
port: answers.port,
user: answers.username,
password: answers.password,
database: answers.database,
multipleStatements: true
},
"meta": {
"tn": "xc_evolutions",
"dbAlias": "db",
"api": {
"type": answers.apiType,
"prefix": "",
"graphqlDepthLimit": 10
meta: {
tn: 'xc_evolutions',
dbAlias: 'db',
api: {
type: answers.apiType,
prefix: '',
graphqlDepthLimit: 10
},
"inflection": {
"tn": "none",
"cn": "none"
inflection: {
tn: 'none',
cn: 'none'
}
}
}
],
"apiClient": {
"data": []
apiClient: {
data: []
}
}
},
"workingEnv": "dev",
"seedsFolder": "seeds",
"queriesFolder": "queries",
"apisFolder": "apis",
"projectType": answers.apiType,
"type": "docker",
"language": "ts",
"apiClient": {
"data": []
workingEnv: 'dev',
seedsFolder: 'seeds',
queriesFolder: 'queries',
apisFolder: 'apis',
projectType: answers.apiType,
type: 'docker',
language: 'ts',
apiClient: {
data: []
},
"auth": {
"jwt": {
"secret": uuidv4(),
"dbAlias": "db"
auth: {
jwt: {
secret: uuidv4(),
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;`);
} else if (answers.projectType === 'mvc') {
console.log(`
1. Install our npm package using following command
@ -568,7 +621,8 @@ class NewMgr {
2. Add the following code in your existing express project
\t${`const {Noco} = require("nocodb");
\t${
`const {Noco} = require("nocodb");
\tnew Noco({
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') {
const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`;
// console.log(`
// 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}
//
//
// Then visit http://localhost:8080/xc to access the Dashboard
//
// `)
// console.log(`
// 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}
//
//
// Then visit http://localhost:8080/xc to access the Dashboard
//
// `)
const linuxHost = os.type() === 'Linux' ? '--net=host' : '';
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`);
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`
);
}
// args.url.push(url);
//
// args.language = languageMapping[answers.programmingLanguage];
// return OldNewMgr.testConnection(args)
}
public static async testConnection({url}) {
public static async testConnection({ url }) {
for (const u of url) {
const parsedUrlData = URL.parse(u, true);
const queryParams = parsedUrlData.query;
@ -681,29 +731,30 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
port: +parsedUrlData.port,
user: queryParams.u,
password: queryParams.p,
database: client === 'pg' ? 'postgres' : (client === 'mssql' ? undefined : null)
database:
client === 'pg' ? 'postgres' : client === 'mssql' ? undefined : null
}
};
try {
const knex = require('knex')(config)
await knex.raw("SELECT 1+1 as data");
const knex = require('knex')(config);
await knex.raw('SELECT 1+1 as data');
} 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 true;
}
public static async isPortOpen(host, port) {
try {
return await tcpPortUsed.check(+port, host)
return await tcpPortUsed.check(+port, host);
} catch (e) {
console.log(e)
console.log(`\n😩 ${host}:${port} is not reachable please check\n`.red.bold)
console.log(e);
console.log(
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
);
return true;
}
}
@ -715,4 +766,3 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
}
export default NewMgr;

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

@ -6,7 +6,7 @@ import URL from 'url';
import('colors');
let tcpPortUsed = require('tcp-port-used');
const tcpPortUsed = require('tcp-port-used');
const dbDefaults = {
mysql: {
@ -36,22 +36,20 @@ const dbDefaults = {
username: 'sa',
password: '',
database: ''
},
}
};
const apiTypeMapping = {
'GRAPHQL APIs': 'graphql',
'REST APIs': 'rest',
'gRPC APIs': 'grpc'
}
};
const languageMapping = {
'Javascript': 'js',
'Typescript': 'ts',
}
Javascript: 'js',
Typescript: 'ts'
};
class OldNewMgr {
/**
*
* Does the below :
@ -64,161 +62,169 @@ class OldNewMgr {
* @returns {Promise<string|string|boolean|*>}
*/
public static async getNewProjectInput(args) {
if (args._.length < 2) {
const usage = '\n$ xc new project_name'.green.bold
console.log(`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red.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
);
return false;
}
/* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults);
args.url = []
args.url = [];
const answers = await inquirer
.prompt([
{
name: 'type',
type: 'list',
message: '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'mysql',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
const answers = await inquirer.prompt([
{
name: 'type',
type: 'list',
message: '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'mysql',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
},
{
name: 'host',
type: 'input',
message: '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host;
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'port',
type: 'number',
message: '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port;
},
{
name: 'host',
type: 'input',
message: '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color;
}
},
{
name: 'port',
type: 'number',
message: '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port
},
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color
}
},
validate(port, answers) {
let done = this.async();
OldNewMgr.isPortOpen(answers.host, port).then(isOpen => {
validate(port, answers) {
const done = this.async();
OldNewMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) {
done(null, true)
done(null, true);
} else {
// 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);
}
}).catch(done)
},
when({type}) {
return type !== 'sqlite3'
}
})
.catch(done);
},
{
name: 'username',
type: 'input',
message: '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'username',
type: 'input',
message: '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username;
},
{
name: 'password',
type: 'input',
mask: true,
message: '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('')
},
when({type}) {
return type !== 'sqlite3'
}
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
{
name: 'database',
type: 'input',
default(_ans) {
return args._[1] + '_dev';
},
message: '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'password',
type: 'input',
mask: true,
message: '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('');
},
{
name: 'projectType',
type: 'list',
message: '🚀 Enter API type to generate\t:',
choices: ['REST APIs', 'GRAPHQL APIs'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'database',
type: 'input',
default(_ans) {
return args._[1] + '_dev';
},
{
name: 'programmingLanguage',
type: 'list',
message: '🚀 Enter preferred programming language\t:',
choices: ['Javascript', 'Typescript'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
message: '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'projectType',
type: 'list',
message: '🚀 Enter API type to generate\t:',
choices: ['REST APIs', 'GRAPHQL APIs'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'programmingLanguage',
type: 'list',
message: '🚀 Enter preferred programming language\t:',
choices: ['Javascript', 'Typescript'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
])
}
]);
// console.log(answers);
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);
}
/* if not valid retry getting right input */
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);
}
@ -229,7 +235,11 @@ class OldNewMgr {
// await Util.runCmd(`cd ${args.folder}`);
/* 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';
switch (answers.projectType) {
case 'REST APIs':
@ -249,13 +259,10 @@ class OldNewMgr {
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) {
const parsedUrlData = URL.parse(u, true);
const queryParams = parsedUrlData.query;
@ -267,34 +274,33 @@ class OldNewMgr {
port: +parsedUrlData.port,
user: queryParams.u,
password: queryParams.p,
database: client === 'pg' ? 'postgres' : (client === 'mssql' ? undefined : null)
database:
client === 'pg' ? 'postgres' : client === 'mssql' ? undefined : null
}
};
try {
const knex = require('knex')(config)
await knex.raw("SELECT 1+1 as data");
const knex = require('knex')(config);
await knex.raw('SELECT 1+1 as data');
} 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 true;
}
public static async isPortOpen(host, port) {
try {
return await tcpPortUsed.check(+port, host)
return await tcpPortUsed.check(+port, host);
} catch (e) {
console.log(e)
console.log(`\n😩 ${host}:${port} is not reachable please check\n`.red.bold)
console.log(e);
console.log(
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
);
return true;
}
}
}
export default OldNewMgr;

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

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

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

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

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

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

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

@ -1,5 +1,7 @@
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: [
'Super slick!',
'Very handy!',
@ -64,7 +66,6 @@ export default {
'Woah, Extremely Interesting!',
'Woah, So useful!',
'Super slick API Framework!',
'Very handy API Framework!',
'Impressive API Framework!',
@ -86,17 +87,11 @@ export default {
'Extremely Interesting API Framework!',
'So useful API Framework',
'Cool Stuff!',
'Woha!',
'I\'m amazed by how well this works!',
'I\'m impressed by how well this works!',
"I'm amazed by how well this works!",
"I'm impressed by how well this works!"
],
suffix: [
'https://github.com/nocodb/nocodb',
'www.nocodb.com'
]
}
suffix: ['https://github.com/nocodb/nocodb', 'www.nocodb.com']
};

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

@ -1,10 +1,10 @@
import chalkPipe from 'chalk-pipe';
import inquirer from 'inquirer';
import path from 'path';
import tcpPortUsed from 'tcp-port-used';
import URL from 'url';
import Util from "../util/Util";
import path from 'path';
import Lang, {STR} from "../util/Lang";
import Lang, { STR } from '../util/Lang';
import Util from '../util/Util';
import('colors');
@ -36,12 +36,10 @@ const dbDefaults = {
username: 'sa',
password: '',
database: ''
},
}
};
class TryMgr {
/**
*
* Does the below :
@ -57,139 +55,151 @@ class TryMgr {
let dbUrl;
if (args._[0] !== 't' && args._[0] !== 'try') {
if ( args._[1] === 'rest') {
if (args._[1] === 'rest') {
dbUrl = `sqlite3://sqlite3?d=${path.join(__dirname, 'sakila.db')}`;
} 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 {
/* Construct database URL from prompt */
const dbTypes = Object.keys(dbDefaults);
args.url = []
args.url = [];
const finalAnswers = await inquirer
.prompt([
{
name: 'type',
type: 'list',
message: Lang.getString(STR.DB_TYPE),// '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'mysql2',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
const finalAnswers = await inquirer.prompt([
{
name: 'type',
type: 'list',
message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
choices: dbTypes.map(t => ({
name: t,
value: t,
short: t.green.bold
})),
default: 'mysql2',
transformer(color) {
return chalkPipe(color)(color.green.bold);
}
},
{
name: 'host',
type: 'input',
message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host;
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'port',
type: 'number',
message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port;
},
{
name: 'host',
type: 'input',
message: Lang.getString(STR.DB_HOST),// '👉 Enter database host name\t:',
default(ans) {
return dbDefaults[ans.type].host
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color;
}
},
{
name: 'port',
type: 'number',
message: Lang.getString(STR.DB_PORT),// '👉 Enter database port number\t:',
default(ans) {
return dbDefaults[ans.type].port
},
transformer(color) {
try {
return color.green.bold;
} catch (e) {
return color
}
},
validate(port, answers) {
const done = this.async();
if (answers.host === 'host.docker.internal' || answers.host === 'docker.for.win.localhost') {
done(null, true)
} else {
TryMgr.isPortOpen(answers.host, port).then(isOpen => {
validate(port, answers) {
const done = this.async();
if (
answers.host === 'host.docker.internal' ||
answers.host === 'docker.for.win.localhost'
) {
done(null, true);
} else {
TryMgr.isPortOpen(answers.host, port)
.then(isOpen => {
if (isOpen) {
done(null, true)
done(null, true);
} else {
// 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);
}
}).catch(done)
}
},
when({type}) {
return type !== 'sqlite3'
})
.catch(done);
}
},
{
name: 'username',
type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username
},
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'username',
type: 'input',
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
default(ans) {
return dbDefaults[ans.type].username;
},
{
name: 'password',
type: 'input',
mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('')
},
when({type}) {
return type !== 'sqlite3'
}
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
{
name: 'database',
type: 'input',
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'password',
type: 'input',
mask: true,
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
transformer(color) {
return new Array(color.length).fill('*'.green.bold).join('');
},
{
name: 'apiType',
type: 'list',
message: Lang.getString(STR.DB_API), // '🚀 Enter API type to generate\t:',
choices: ['REST APIs', 'GRAPHQL APIs', 'gRPC APIs'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({type}) {
return type !== 'sqlite3'
}
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'database',
type: 'input',
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
when({ type }) {
return type !== 'sqlite3';
}
},
{
name: 'apiType',
type: 'list',
message: Lang.getString(STR.DB_API), // '🚀 Enter API type to generate\t:',
choices: ['REST APIs', 'GRAPHQL APIs', 'gRPC APIs'].map(t => ({
name: t,
value: t,
short: t.green.bold
})),
transformer(color) {
return chalkPipe(color)(color.green.bold);
},
])
when({ type }) {
return type !== 'sqlite3';
}
}
]);
// console.log(finalAnswers);
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);
}
@ -200,7 +210,6 @@ class TryMgr {
}*/
//
/* prepare the args */
// 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';
@ -218,16 +227,19 @@ class TryMgr {
finalAnswers.apiType = 'rest';
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(`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) {
const parsedUrlData = URL.parse(u, true);
const queryParams = parsedUrlData.query;
@ -235,37 +247,41 @@ class TryMgr {
const config = {
client,
connection: {
database: client === 'pg' ? 'postgres' : (client === 'mssql' ? undefined : null),
database:
client === 'pg'
? 'postgres'
: client === 'mssql'
? undefined
: null,
host: parsedUrlData.hostname,
password: queryParams.p,
port: +parsedUrlData.port,
user: queryParams.u,
user: queryParams.u
}
};
try {
const knex = require('knex')(config)
await knex.raw("SELECT 1+1 as data");
const knex = require('knex')(config);
await knex.raw('SELECT 1+1 as data');
} 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 true;
}
public static async isPortOpen(host, port) {
try {
return await tcpPortUsed.check(+port, host)
return await tcpPortUsed.check(+port, host);
} catch (e) {
console.log(e)
console.log(`\n😩 ${host}:${port} is not reachable please check\n`.red.bold)
console.log(e);
console.log(
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
);
return true;
}
}
}
export default TryMgr;

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

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

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

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

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

@ -3,40 +3,30 @@
*/
'use strict';
import inquirer from "inquirer";
import inquirer from 'inquirer';
class RunOrDownload {
public static async handle(_args) {
const answers = await inquirer.prompt([
{
choices: [
'Open the app!',
'Download it for FREE'
],
message: 'Your XGENE desktop app is not open - do you want to ?',
name: 'action',
type: 'rawlist'
}
]);
{
choices: ['Open the app!', 'Download it for FREE'],
message: 'Your XGENE desktop app is not open - do you want to ?',
name: 'action',
type: 'rawlist'
}
]);
switch (answers.action) {
case 'Open app!':
break;
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;
}
}
}
export default RunOrDownload;

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

@ -3,15 +3,16 @@ import english from './english.json';
import translated from './translated.json';
/* 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 = {};
for (const {symbol, text} of [english, ...translated].sort((a, b) => a.symbol.localeCompare(b.symbol))) {
formattedTranslate [symbol] = text.split(/\s*\|\|\s*/);
for (const { symbol, text } of [english, ...translated].sort((a, b) =>
a.symbol.localeCompare(b.symbol)
)) {
formattedTranslate[symbol] = text.split(/\s*\|\|\s*/);
}
const dummy: any = new Date();
const offset: any = -dummy.getTimezoneOffset();
const locale: string = offset === 330 ? 'en-IN' : osLocale.sync();
@ -29,14 +30,10 @@ enum STR {
PROJECT_TYPE
}
class Lang {
// @ts-ignore
public static getString(str: STR) {
switch (locale) {
case 'en':
case 'en-GB':
case 'en-AU':
@ -45,7 +42,7 @@ class Lang {
case 'en-US':
default:
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.en?.[str]}\t:`;
case 'zh':
case 'zh-Hans':
case 'zh-CN':
@ -78,7 +75,7 @@ class Lang {
case 'es-US':
case 'es-VE':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.es?.[str]}\t:`;
case 'fi':
case 'fi-FI':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.fi?.[str]}\t:`;
@ -89,7 +86,7 @@ class Lang {
case 'fr-BE':
case 'fr-CH':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.fr?.[str]}\t:`;
case 'it':
case 'it-IT':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.it?.[str]}\t:`;
@ -97,7 +94,7 @@ class Lang {
case 'ja':
case 'ja-JP':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.ja?.[str]}\t:`;
case 'ko':
case 'ko-KR':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.ko?.[str]}\t:`;
@ -121,7 +118,6 @@ class Lang {
case 'sv-SE':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.sv?.[str]}\t:`;
case 'th':
case 'th-TH':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.th?.[str]}\t:`;
@ -142,13 +138,8 @@ class Lang {
case 'vi-VN':
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.vi?.[str]}\t:`;
}
}
}
export default Lang;
export {
STR
};
export { STR };

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

@ -1,9 +1,7 @@
import osLocale from 'os-locale';
class Locales {
public static getPrompt() {
const x = new Date();
const offset = -x.getTimezoneOffset();
@ -11,7 +9,6 @@ class Locales {
const locale = offset === 330 ? 'en-IN' : osLocale.sync();
switch (locale) {
case 'en':
case 'en-GB':
case 'en-AU':
@ -20,7 +17,8 @@ class Locales {
case 'en-US':
default:
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
'Facebook',
@ -29,10 +27,12 @@ class Locales {
'Reddit',
'Next time',
'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;
case 'zh':
@ -47,17 +47,18 @@ class Locales {
'WeChat',
'Github - ⭐ or 👀 repo',
'豆瓣', // douban
'新浪微博',// weibo
'新浪微博', // weibo
'Renren',
'Line',
'Telegram',
'Next time',
'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;
case 'en-IN':
@ -71,14 +72,14 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'de':
case 'de-DE':
case 'de-CH':
@ -94,18 +95,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'el':
case 'el-GR':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -114,11 +116,12 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'es':
@ -134,7 +137,8 @@ class Locales {
case 'es-US':
case 'es-VE':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -143,17 +147,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'fa':
case 'fa-IR':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -162,17 +168,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'fi':
case 'fi-FI':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -181,22 +189,22 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'fr':
case 'fr-CA':
case 'fr-FR':
case 'fr-BE':
case 'fr-CH':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -205,17 +213,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'ga':
case 'ga-IE':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -224,17 +234,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'he':
case 'he-IL':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -243,17 +255,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'it':
case 'it-IT':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -262,18 +276,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'ja':
case 'ja-JP':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Line',
'Linkedin',
@ -284,17 +299,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'ko':
case 'ko-KR':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Line',
'Linkedin',
@ -303,20 +320,22 @@ class Locales {
'WhatsApp',
'WeChat',
'豆瓣', // douban
'新浪微博',// weibo
'新浪微博', // weibo
'Telegram',
'Next time',
'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;
case 'mn-MN':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -324,20 +343,21 @@ class Locales {
'WhatsApp',
'Next time',
'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;
case 'nl':
case 'nl-BE':
case 'nl-NL':
case 'nn-NO':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -345,19 +365,20 @@ class Locales {
'WhatsApp',
'Next time',
'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;
case 'pt':
case 'pt-BR':
case 'pt-PT':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -365,17 +386,19 @@ class Locales {
'WhatsApp',
'Next time',
'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;
case 'ru':
case 'ru-RU':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'OKru',
'Telegram',
@ -386,18 +409,19 @@ class Locales {
'WhatsApp',
'Next time',
'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;
case 'sv':
case 'sv-SE':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -405,18 +429,19 @@ class Locales {
'WhatsApp',
'WeChat',
'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;
case 'th':
case 'th-TH':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -425,17 +450,19 @@ class Locales {
'Telegram',
'Next time',
'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;
case 'tl':
case 'tl-PH':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -444,18 +471,19 @@ class Locales {
'WeChat',
'Telegram',
'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;
case 'tr':
case 'tr-TR':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -463,17 +491,19 @@ class Locales {
'WhatsApp',
'Telegram',
'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;
case 'uk':
case 'uk-UA':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'OKru',
// 'Reddit',
@ -485,17 +515,19 @@ class Locales {
'Wykop',
'Next time',
'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;
case 'vi':
case 'vi-VN':
prompt = {
choices: ['Twitter',
choices: [
'Twitter',
'Github - ⭐ or 👀 repo',
'Linkedin',
// 'Reddit',
@ -504,20 +536,17 @@ class Locales {
'WeChat',
'Telegram',
'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;
}
return prompt;
}
}
export default Locales;

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

@ -2,19 +2,23 @@ import path from 'path';
import shell from 'shelljs';
class Util {
public static getShortVersion(args) {
const shortVersion = JSON.parse(JSON.stringify(args));
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;
}
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';
}
@ -34,7 +38,9 @@ Commands:
public static manNew() {
return `
${'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}
${'xc new'.bold} ${'<projectName>'.bold}
@ -54,7 +60,7 @@ ${'VARIATIONS :'.bold}
- Takes in database credentials and API type as input
- Database can be new or existing database
- Creates a new folder by name 'airbnb'
`
`;
}
public static manDocker() {
@ -77,13 +83,15 @@ ${'VARIATIONS :'.bold}
- Database can be new or existing database
- Scaffolds REST/GraphQL/gRPC APIs for the database specified
- These database can be already existing or new databases.
`
`;
}
public static manGenApisRest() {
return `
${'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}
${'xc gen.apis.rest'.bold} [${'-u'.bold} DatabaseURL(s)]
@ -92,38 +100,56 @@ ${'VARIATIONS :'.bold}
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
${'-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 pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce
For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce
${'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'
- Uses current directory as project name
- If database exists - REST APIs will be created for the tables within it.
- 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'
${'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'
${`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'.
- These database can be already existing or new databases.
`
`;
}
public static manGenApisGraphql() {
return `
${'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}
${'xc gen.apis.graphql'.bold} [${'-u'.bold} DatabaseURL(s)]
@ -132,56 +158,84 @@ ${'VARIATIONS :'.bold}
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
${'-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 pg : pg://localhost:5432?u=postgres&p=password&d=ecommerce
For mssql : mssql://localhost:1433?u=sa&p=Password123.&d=ecommerce
${'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'
- Uses current directory as project name
- If database exists - GraphQL APIs will be created for the tables within it.
- 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'
${'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'
${`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'.
- These database can be already existing or new databases.
`
`;
}
public static manGenModule() {
return `
${'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 GraphQL project - (resolver, service, middleware, policy, model, meta)
${'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}
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 pg : pg://localhost:5432?u=postgres&p=password&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
${'--service'.bold} Will create service with model - router file will be skipped //todo
${
'--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
${
'--service'.bold
} Will create service with model - router file will be skipped //todo
${'VARIATIONS :'.bold}
@ -206,13 +260,15 @@ ${'VARIATIONS :'.bold}
- All folder/files in respective components will be created in parent table of primary table
`
`;
}
public static manDbMigrateInit() {
return `
${'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
- Instead use ${'xc new'.bold}
- 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}
- Creates migration project of type mysql
- xc db.migrate.sync has to be run after command
`
`;
}
public static manDbMigrateSync() {
return `
${'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
${'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}
The following options are available:
${'--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}
@ -259,7 +321,7 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.sync --env production --dbAlias secondary'.bold}
- Initialises migration for 'db2'(secondary) database within 'production' environment
`
`;
}
public static manDbMigrateList() {
@ -268,7 +330,9 @@ ${'COMMAND : '.bold}
${'xc db.migrate.list'.bold} - Lists all the migrations
${'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}
@ -290,16 +354,20 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.list --env production --dbAlias secondary'.bold}
- Lists all migrations within 'production' environment and 'db2'(secondary) database
`
`;
}
public static manDbMigrateCreate() {
return `
${'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}
${'xc db.migrate.create'.bold} [${'--env'.bold} <environment>] [${'--dbAlias'.bold} <databaseAlias>]
${'xc db.migrate.create'.bold} [${'--env'.bold} <environment>] [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold}
@ -320,7 +388,7 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.create --env production --dbAlias secondary'.bold}
- Creates a migration within 'production' environment and 'db2'(secondary) database
`
`;
}
public static manDbMigrateUp() {
@ -329,7 +397,11 @@ ${'COMMAND : '.bold}
${'xc db.migrate.up'.bold} - Applies all pending migrations
${'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}
@ -353,18 +425,26 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.up --env production --steps 1'.bold}
- 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
`
`;
}
public static manDbMigrateDown() {
return `
${'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}
${'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}
@ -388,23 +468,29 @@ ${'VARIATIONS :'.bold}
${'xc db.migrate.down --env production --steps 1'.bold}
- 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
`
`;
}
public static manDbMigrateTerm() {
return `
${'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() {
return `
${'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.
${'SYNOPSIS : '.bold}
@ -427,13 +513,15 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold}
${'xc component.add cache'.bold}
- Adds a cache component
`
`;
}
public static manAppInstall() {
return `
${'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}
${'xc app.install'.bold}
@ -449,13 +537,15 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold}
${'xc app.install'.bold}
`
`;
}
public static manAppOpen() {
return `
${'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}
${'xc app.open'.bold}
@ -471,10 +561,9 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold}
${'xc app.open'.bold}
`
`;
}
public static manPermissionsSet() {
return `
${'COMMAND : '.bold}
@ -482,17 +571,27 @@ ${'COMMAND : '.bold}
${'SYNOPSIS : '.bold}
# 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
${'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}
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
${'permissions(s)'.bold}Permissions - read | write | get | post | put | delete | patch | resolverFunc | $ - means all permissions
${
'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
${
'permissions(s)'.bold
}Permissions - read | write | get | post | put | delete | patch | resolverFunc | $ - means all permissions
${'VARIATIONS :'.bold}
None
@ -509,7 +608,7 @@ ${'VARIATIONS :'.bold}
${'xc permissions.set $ $ read=1 write=1'.bold}
- For 'all' models 'all' user types SET 'read' and 'write' permission
`
`;
}
// todo
@ -536,10 +635,9 @@ ${'VARIATIONS :'.bold}
${'Examples with notes : '.bold}
${'xc permissions.get blog'.bold}
- Get all permissions of blog model `
- Get all permissions of blog model `;
}
public static manPermissionsUserAdd() {
return `
${'COMMAND : '.bold}
@ -564,10 +662,9 @@ ${'VARIATIONS :'.bold}
${'xc permissions.role.add manager'.bold}
- Adds user role 'manager' to all the models
`
`;
}
public static manPermissionsUserDelete() {
return `
${'COMMAND : '.bold}
@ -590,10 +687,9 @@ ${'VARIATIONS :'.bold}
${'xc permissions.role.delete manager'.bold}
- deletes user role 'manager' from all the models
`
`;
}
public static manPermissionsUserRename() {
return `
${'COMMAND : '.bold}
@ -617,23 +713,28 @@ ${'VARIATIONS :'.bold}
${'xc permissions.role.rename manager StaffManager'.bold}
- Renames user role from 'manager' to 'StaffManager' in all the models
`
`;
}
public static manProjectMetaExport() {
return `
${'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}
${'xc meta.export'.bold} ${'--env'.bold} <environment> [${'--dbAlias'.bold} <databaseAlias>]
${'xc meta.export'.bold} ${'--env'.bold} <environment> [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold}
The following options are available:
${'--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}
@ -645,8 +746,7 @@ ${'VARIATIONS :'.bold}
${'xc meta.export --env production --dbAlias db2'.bold}
- Exports metadata for 'db2' database in 'production' environment
`
`;
}
public static manProjectMetaReset() {
@ -655,13 +755,17 @@ ${'COMMAND : '.bold}
${'xc meta.reset'.bold} - Clears all meta table data
${'SYNOPSIS : '.bold}
${'xc meta.reset'.bold} ${'--env'.bold} <environment> [${'--dbAlias'.bold} <databaseAlias>]
${'xc meta.reset'.bold} ${'--env'.bold} <environment> [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold}
The following options are available:
${'--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}
@ -673,23 +777,28 @@ ${'VARIATIONS :'.bold}
${'xc meta.reset --env production --dbAlias db2'.bold}
- Clears metadata for 'db2' database in 'production' environment
`
`;
}
public static manProjectMetaImport() {
return `
${'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}
${'xc meta.import'.bold} ${'--env'.bold} <environment> [${'--dbAlias'.bold} <databaseAlias>]
${'xc meta.import'.bold} ${'--env'.bold} <environment> [${
'--dbAlias'.bold
} <databaseAlias>]
${'OPTIONS :'.bold}
The following options are available:
${'--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}
@ -701,18 +810,13 @@ ${'VARIATIONS :'.bold}
${'xc meta.import --env production --dbAlias db2'.bold}
- Imports metadata for 'db2' database in 'production' environment
`
`;
}
public static showHelpForCommand(args) {
try {
switch (args._[1]) {
case 'new' :
case 'new':
console.log(Util.manNew());
break;
@ -870,14 +974,12 @@ ${'VARIATIONS :'.bold}
//
// /**************** END : Docker ****************/
default:
break;
}
} catch (e) {
throw e;
}
}
public static async runCmd(str) {
@ -891,24 +993,17 @@ ${'VARIATIONS :'.bold}
public static escapeShellArg(cmd) {
return '"' + cmd.replace(/(["'$`\\])/g, '\\$1') + '"';
};
}
public async play(sound) {
switch (sound) {
case -1:
break;
case 'fun':
break;
}
}
}
export default Util;

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

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

Loading…
Cancel
Save