mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
8.2 KiB
287 lines
8.2 KiB
import chalkPipe from 'chalk-pipe'; |
|
import inquirer from 'inquirer'; |
|
import path from 'path'; |
|
import tcpPortUsed from 'tcp-port-used'; |
|
import URL from 'url'; |
|
import Lang, { STR } from '../util/Lang'; |
|
import Util from '../util/Util'; |
|
|
|
import('colors'); |
|
|
|
const dbDefaults = { |
|
mysql2: { |
|
host: 'localhost', |
|
port: '3306', |
|
username: 'root', |
|
password: '', |
|
database: '' |
|
}, |
|
pg: { |
|
host: 'localhost', |
|
port: '5432', |
|
username: 'postgres', |
|
password: '', |
|
database: '' |
|
}, |
|
mssql: { |
|
host: 'localhost', |
|
port: '1433', |
|
username: 'sa', |
|
password: '', |
|
database: '' |
|
}, |
|
sqlite3: { |
|
host: 'localhost', |
|
port: '1433', |
|
username: 'sa', |
|
password: '', |
|
database: '' |
|
} |
|
}; |
|
|
|
class TryMgr { |
|
/** |
|
* |
|
* Does the below : |
|
* - Get database input and make a DB URL from it. |
|
* - Create new folder and 'cd' to that folder. |
|
* - Return true/success |
|
* - Else failure |
|
* |
|
* @param args |
|
* @returns {Promise<string|string|boolean|*>} |
|
*/ |
|
public static async getProjectInput(args): Promise<any> { |
|
let dbUrl; |
|
|
|
if (args._[0] !== 't' && args._[0] !== 'try') { |
|
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`; |
|
} |
|
} else { |
|
/* Construct database URL from prompt */ |
|
const dbTypes = Object.keys(dbDefaults); |
|
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); |
|
} |
|
}, |
|
{ |
|
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; |
|
}, |
|
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 => { |
|
if (isOpen) { |
|
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 |
|
); |
|
process.exit(0); |
|
} |
|
}) |
|
.catch(done); |
|
} |
|
}, |
|
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; |
|
}, |
|
transformer(color) { |
|
return chalkPipe(color)(color.green.bold); |
|
}, |
|
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(''); |
|
}, |
|
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 |
|
); |
|
process.exit(0); |
|
} |
|
|
|
/* if not valid retry getting right input */ |
|
/* if (!finalAnswers.database) { |
|
console.log('\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold); |
|
this.getNewProjectInput(args); |
|
}*/ |
|
// |
|
|
|
/* prepare the args */ |
|
// const url = `${finalAnswers.type}://${finalAnswers.host}:${finalAnswers.port}?u=${finalAnswers.username}&p=${finalAnswers.password}&d=${finalAnswers.database}&api=${apiTypeMapping[finalAnswers.projectType]}`; |
|
// args._[0] = finalAnswers.projectType === 'REST APIs' ? 'gar' : 'gag'; |
|
switch (finalAnswers.apiType) { |
|
case 'REST APIs': |
|
finalAnswers.apiType = 'rest'; |
|
break; |
|
case 'GRAPHQL APIs': |
|
finalAnswers.apiType = 'graphql'; |
|
break; |
|
case 'gRPC APIs': |
|
finalAnswers.apiType = 'grpc'; |
|
break; |
|
default: |
|
finalAnswers.apiType = 'rest'; |
|
break; |
|
} |
|
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` |
|
); |
|
} |
|
|
|
public static async testConnection({ url }) { |
|
for (const u of url) { |
|
const parsedUrlData = URL.parse(u, true); |
|
const queryParams = parsedUrlData.query; |
|
const client = parsedUrlData.protocol.slice(0, -1); |
|
const config = { |
|
client, |
|
connection: { |
|
database: |
|
client === 'pg' |
|
? 'postgres' |
|
: client === 'mssql' |
|
? undefined |
|
: null, |
|
host: parsedUrlData.hostname, |
|
password: queryParams.p, |
|
port: +parsedUrlData.port, |
|
user: queryParams.u |
|
} |
|
}; |
|
|
|
try { |
|
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); |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
public static async isPortOpen(host, port) { |
|
try { |
|
return await tcpPortUsed.check(+port, host); |
|
} catch (e) { |
|
console.log(e); |
|
console.log( |
|
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold |
|
); |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
export default TryMgr;
|
|
|