From 1fab1588802a8219fc3bd75eaac9f39a310c1ecf Mon Sep 17 00:00:00 2001 From: Jim LAURIE Date: Fri, 1 Feb 2019 14:56:46 +0100 Subject: [PATCH 1/3] Add quickstart mode --- packages/strapi-generate-new/lib/before.js | 398 +++++++++++---------- packages/strapi/bin/strapi-new.js | 13 +- packages/strapi/bin/strapi.js | 1 + packages/strapi/package.json | 3 +- 4 files changed, 226 insertions(+), 189 deletions(-) diff --git a/packages/strapi-generate-new/lib/before.js b/packages/strapi-generate-new/lib/before.js index 3f1a1fea43..ebd38a2e13 100644 --- a/packages/strapi-generate-new/lib/before.js +++ b/packages/strapi-generate-new/lib/before.js @@ -62,13 +62,11 @@ module.exports = (scope, cb) => { // ... } - console.log('Let\s configurate the connection to your database:'); - if (hasDatabaseConfig) { console.log(`Database determined by CLI args: ${scope.database.settings.client}`); } - const connectionValidation = () => { + const connectionValidation = async () => { const databaseChoices = [ { name: 'SQLite', @@ -103,10 +101,25 @@ module.exports = (scope, cb) => { } ]; - inquirer + const answers = await inquirer .prompt([ { - when: !hasDatabaseConfig, + when: !scope.quick, + type: 'list', + name: 'type', + message: 'Choose your installation type', + choices: [{ + name: 'Quickstart (recommended)', + value: 'quick' + }, { + name: 'Custom (manual settings)', + value: 'custom' + }] + }, + { + when: (answers) => { + return !hasDatabaseConfig && answers.type === 'custom'; + }, type: 'list', name: 'client', message: 'Choose your main database:', @@ -117,203 +130,214 @@ module.exports = (scope, cb) => { } } } - ]) - .then(answers => { - if (hasDatabaseConfig) { - const databaseChoice = _.find(databaseChoices, ['value.database', scope.database.settings.client]); - scope.database.connector = databaseChoice.value.connector; - answers.client = { - ...databaseChoice.value - }; - } else { - _.assign(scope.database, { - connector: answers.client.connector, - settings: { - client: answers.client.database + ]); + + scope.quick = answers.type === 'quick' || scope.quick; + const isQuick = scope.quick; + + if (isQuick) { + answers.client = databaseChoices[0].value; + } + + if (hasDatabaseConfig) { + const databaseChoice = _.find(databaseChoices, ['value.database', scope.database.settings.client]); + scope.database.connector = databaseChoice.value.connector; + answers.client = { + ...databaseChoice.value + }; + } else { + _.assign(scope.database, { + connector: answers.client.connector, + settings: { + client: answers.client.database + }, + options: {} + }); + } + + scope.client = answers.client; + + const asyncFn = [ + new Promise(async resolve => { + const isMongo = scope.client.database === 'mongo'; + const isSQLite = scope.database.settings.client === 'sqlite'; + + let answers = await inquirer + .prompt([ + { + when: !hasDatabaseConfig && !isSQLite, + type: 'input', + name: 'database', + message: 'Database name:', + default: _.get(scope.database, 'database', scope.name) }, - options: {} - }); + { + when: !hasDatabaseConfig && !isSQLite, + type: 'input', + name: 'host', + message: 'Host:', + default: _.get(scope.database, 'host', '127.0.0.1') + }, + { + when: !hasDatabaseConfig && isMongo, + type: 'boolean', + name: 'srv', + message: '+srv connection:', + default: _.get(scope.database, 'srv', false) + }, + { + when: !hasDatabaseConfig && !isSQLite, + type: 'input', + name: 'port', + message: `Port${isMongo ? ' (It will be ignored if you enable +srv)' : ''}:`, + default: (answers) => { // eslint-disable-line no-unused-vars + if (_.get(scope.database, 'port')) { + return scope.database.port; + } + + const ports = { + mongo: 27017, + postgres: 5432, + mysql: 3306 + }; + + return ports[scope.client.database]; + } + }, + { + when: !hasDatabaseConfig && !isSQLite, + type: 'input', + name: 'username', + message: 'Username:', + default: _.get(scope.database, 'username', undefined) + }, + { + when: !hasDatabaseConfig && !isSQLite, + type: 'password', + name: 'password', + message: 'Password:', + mask: '*', + default: _.get(scope.database, 'password', undefined) + }, + { + when: !hasDatabaseConfig && isMongo, + type: 'input', + name: 'authenticationDatabase', + message: 'Authentication database (Maybe "admin" or blank):', + default: _.get(scope.database, 'authenticationDatabase', undefined) + }, + { + when: !hasDatabaseConfig && !isSQLite, + type: 'boolean', + name: 'ssl', + message: 'Enable SSL connection:', + default: _.get(scope.database, 'ssl', false) + }, + { + when: !hasDatabaseConfig && isSQLite && !isQuick, + type: 'input', + name: 'filename', + message: 'Filename:', + default: () => '.tmp/data.db' + } + ]); + + if (isQuick) { + answers.filename = '.tmp/data.db'; } - scope.client = answers.client; - const asyncFn = [ - new Promise(resolve => { - const isMongo = scope.client.database === 'mongo'; - const isSQLite = scope.database.settings.client === 'sqlite'; + if (hasDatabaseConfig) { + answers = _.merge((_.omit(scope.database.settings, ['client'])), scope.database.options); + } - inquirer - .prompt([ - { - when: !hasDatabaseConfig && !isSQLite, - type: 'input', - name: 'database', - message: 'Database name:', - default: _.get(scope.database, 'database', scope.name) - }, - { - when: !hasDatabaseConfig && !isSQLite, - type: 'input', - name: 'host', - message: 'Host:', - default: _.get(scope.database, 'host', '127.0.0.1') - }, - { - when: !hasDatabaseConfig && isMongo, - type: 'boolean', - name: 'srv', - message: '+srv connection:', - default: _.get(scope.database, 'srv', false) - }, - { - when: !hasDatabaseConfig && !isSQLite, - type: 'input', - name: 'port', - message: `Port${isMongo ? ' (It will be ignored if you enable +srv)' : ''}:`, - default: (answers) => { // eslint-disable-line no-unused-vars - if (_.get(scope.database, 'port')) { - return scope.database.port; - } + scope.database.settings.host = answers.host; + scope.database.settings.port = answers.port; + scope.database.settings.database = answers.database; + scope.database.settings.username = answers.username; + scope.database.settings.password = answers.password; - const ports = { - mongo: 27017, - postgres: 5432, - mysql: 3306 - }; + if (answers.filename) { + scope.database.settings.filename = answers.filename; + } + if (answers.srv) { + scope.database.settings.srv = _.toString(answers.srv) === 'true'; + } + if (answers.authenticationDatabase) { + scope.database.options.authenticationDatabase = answers.authenticationDatabase; + } - return ports[scope.client.database]; - } - }, - { - when: !hasDatabaseConfig && !isSQLite, - type: 'input', - name: 'username', - message: 'Username:', - default: _.get(scope.database, 'username', undefined) - }, - { - when: !hasDatabaseConfig && !isSQLite, - type: 'password', - name: 'password', - message: 'Password:', - mask: '*', - default: _.get(scope.database, 'password', undefined) - }, - { - when: !hasDatabaseConfig && isMongo, - type: 'input', - name: 'authenticationDatabase', - message: 'Authentication database (Maybe "admin" or blank):', - default: _.get(scope.database, 'authenticationDatabase', undefined) - }, - { - when: !hasDatabaseConfig && !isSQLite, - type: 'boolean', - name: 'ssl', - message: 'Enable SSL connection:', - default: _.get(scope.database, 'ssl', false) - }, - { - when: !hasDatabaseConfig && isSQLite, - type: 'input', - name: 'filename', - message: 'Filename:', - default: () => '.tmp/data.db' - } - ]) - .then(answers => { - if (hasDatabaseConfig) { - answers = _.merge((_.omit(scope.database.settings, ['client'])), scope.database.options); - } + // SQLite requirements. + if (isSQLite) { + // Necessary for SQLite configuration (https://knexjs.org/#Builder-insert). + scope.database.options = { + useNullAsDefault: true + }; + } - scope.database.settings.host = answers.host; - scope.database.settings.port = answers.port; - scope.database.settings.database = answers.database; - scope.database.settings.username = answers.username; - scope.database.settings.password = answers.password; - if (answers.filename) { - scope.database.settings.filename = answers.filename; - } - if (answers.srv) { - scope.database.settings.srv = _.toString(answers.srv) === 'true'; - } - if (answers.authenticationDatabase) { - scope.database.options.authenticationDatabase = answers.authenticationDatabase; - } + if (answers.ssl && scope.client.database === 'mongo') { + scope.database.options.ssl = _.toString(answers.ssl) === 'true'; + } else if (answers.ssl) { + scope.database.settings.ssl = _.toString(answers.ssl) === 'true'; + } - // SQLite requirements. - if (isSQLite) { - // Necessary for SQLite configuration (https://knexjs.org/#Builder-insert). - scope.database.options = { - useNullAsDefault: true - }; - } + console.log(); + console.log('⏳ Testing database connection...'); - if (answers.ssl && scope.client.database === 'mongo') { - scope.database.options.ssl = _.toString(answers.ssl) === 'true'; - } else if (answers.ssl) { - scope.database.settings.ssl = _.toString(answers.ssl) === 'true'; - } + resolve(); + }), + new Promise(resolve => { + const isStrapiInstalledWithNPM = packageManager.isStrapiInstalledWithNPM(); + let packageCmd = packageManager.commands('install --prefix', scope.tmpPath); + // Manually create the temp directory for yarn + if (!isStrapiInstalledWithNPM) { + shell.exec(`mkdir ${scope.tmpPath}`); + } - console.log(); - console.log('⏳ Testing database connection...'); + let cmd = `${packageCmd} ${scope.client.connector}@${scope.strapiPackageJSON.version}`; + let linkNodeModulesCommand = `cd ${scope.tmpPath} && npm link ${scope.client.connector}`; - resolve(); - }); - }), - new Promise(resolve => { - const isStrapiInstalledWithNPM = packageManager.isStrapiInstalledWithNPM(); - let packageCmd = packageManager.commands('install --prefix', scope.tmpPath); - // Manually create the temp directory for yarn - if (!isStrapiInstalledWithNPM) { - shell.exec(`mkdir ${scope.tmpPath}`); + if (scope.client.module) { + cmd += ` ${scope.client.module}`; + } + + if (scope.client.connector === 'strapi-hook-bookshelf') { + cmd += ` strapi-hook-knex@${scope.strapiPackageJSON.version}`; + linkNodeModulesCommand += ` && npm link strapi-hook-knex`; + + scope.additionalsDependencies = ['strapi-hook-knex', 'knex']; + } + + exec(cmd, () => { + if (scope.client.module) { + const lock = require(path.join(`${scope.tmpPath}`, '/node_modules/', `${scope.client.module}/package.json`)); + scope.client.version = lock.version; + + if (scope.developerMode === true && scope.client.connector === 'strapi-hook-bookshelf') { + const knexVersion = require(path.join(`${scope.tmpPath}`,`/node_modules/`,`knex/package.json`)); + scope.additionalsDependencies[1] = `knex@${knexVersion.version || 'latest'}`; } + } - let cmd = `${packageCmd} ${scope.client.connector}@${scope.strapiPackageJSON.version}`; - let linkNodeModulesCommand = `cd ${scope.tmpPath} && npm link ${scope.client.connector}`; - - if (scope.client.module) { - cmd += ` ${scope.client.module}`; - } - - if (scope.client.connector === 'strapi-hook-bookshelf') { - cmd += ` strapi-hook-knex@${scope.strapiPackageJSON.version}`; - linkNodeModulesCommand += ` && npm link strapi-hook-knex`; - - scope.additionalsDependencies = ['strapi-hook-knex', 'knex']; - } - - exec(cmd, () => { - if (scope.client.module) { - const lock = require(path.join(`${scope.tmpPath}`, '/node_modules/', `${scope.client.module}/package.json`)); - scope.client.version = lock.version; - - if (scope.developerMode === true && scope.client.connector === 'strapi-hook-bookshelf') { - const knexVersion = require(path.join(`${scope.tmpPath}`,`/node_modules/`,`knex/package.json`)); - scope.additionalsDependencies[1] = `knex@${knexVersion.version || 'latest'}`; - } - } - - if (scope.developerMode) { - exec(linkNodeModulesCommand, () => { - resolve(); - }); - } else { - resolve(); - } + if (scope.developerMode) { + exec(linkNodeModulesCommand, () => { + resolve(); }); - }) - ]; + } else { + resolve(); + } + }); + }) + ]; - Promise.all(asyncFn) - .then(() => { - try { - require(path.join(`${scope.tmpPath}`, '/node_modules/', `${scope.client.connector}/lib/utils/connectivity.js`))(scope, cb.success, connectionValidation); - } catch(err) { - console.log(err); - shell.rm('-r', scope.tmpPath); - cb.error(); - } - }); + Promise.all(asyncFn) + .then(() => { + try { + require(path.join(`${scope.tmpPath}`, '/node_modules/', `${scope.client.connector}/lib/utils/connectivity.js`))(scope, cb.success, connectionValidation); + } catch(err) { + console.log(err); + shell.rm('-r', scope.tmpPath); + cb.error(); + } }); }; diff --git a/packages/strapi/bin/strapi-new.js b/packages/strapi/bin/strapi-new.js index 696a3a1060..614a0f177a 100644 --- a/packages/strapi/bin/strapi-new.js +++ b/packages/strapi/bin/strapi-new.js @@ -11,6 +11,7 @@ const path = require('path'); // Public node modules. const _ = require('lodash'); +const shell = require('shelljs'); // Master of ceremonies for generators. const generate = require('strapi-generate'); @@ -43,7 +44,8 @@ module.exports = function (name, cliArguments) { name, strapiPackageJSON: packageJSON, developerMode, - debug: cliArguments.debug !== undefined + debug: cliArguments.debug !== undefined, + quick: cliArguments.quickstart !== undefined }; const dbArguments = ['dbclient', 'dbhost', 'dbport', 'dbname', 'dbusername', 'dbpassword']; @@ -83,6 +85,15 @@ module.exports = function (name, cliArguments) { error: function returnError(err) { console.log(err); process.exit(1); + }, + + success: () => { + if (scope.quick) { + shell.cd(scope.rootPath); + shell.exec('strapi start', { + stdio: 'inherit' + }); + } } }); }; diff --git a/packages/strapi/bin/strapi.js b/packages/strapi/bin/strapi.js index ab6a344a35..0606a203c6 100755 --- a/packages/strapi/bin/strapi.js +++ b/packages/strapi/bin/strapi.js @@ -54,6 +54,7 @@ program .command('new') .option('-d, --dev', 'Development mode') .option('--debug', 'Display database connection error') + .option('--quickstart', 'Quickstart app creation') .option('--dbclient ', 'Database client') .option('--dbhost ', 'Database host') .option('--dbsrv ', 'Database srv') diff --git a/packages/strapi/package.json b/packages/strapi/package.json index adc19c0e49..8ae2f3bfb8 100644 --- a/packages/strapi/package.json +++ b/packages/strapi/package.json @@ -59,6 +59,7 @@ "ora": "^3.0.0", "rimraf": "^2.6.2", "semver": "^5.4.1", + "shelljs": "^0.8.3", "stack-trace": "0.0.10", "strapi-generate": "3.0.0-alpha.21", "strapi-generate-admin": "3.0.0-alpha.21", @@ -99,4 +100,4 @@ }, "preferGlobal": true, "license": "MIT" -} \ No newline at end of file +} From 4e9ba1280b47ae0933dfd2fc317d22f2f8cd9084 Mon Sep 17 00:00:00 2001 From: Jim LAURIE Date: Fri, 1 Feb 2019 15:19:22 +0100 Subject: [PATCH 2/3] Add documentation --- docs/3.x.x/cli/CLI.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/3.x.x/cli/CLI.md b/docs/3.x.x/cli/CLI.md index 9ebe1d6b9e..c4d15fa931 100644 --- a/docs/3.x.x/cli/CLI.md +++ b/docs/3.x.x/cli/CLI.md @@ -10,7 +10,7 @@ Create a new project ```bash strapi new -options: [--dev|--debug|--dbclient= --dbhost= --dbport= --dbname= --dbusername= --dbpassword= --dbssl= --dbauth= --dbforce] +options: [--dev|--debug|--quickstart|--dbclient= --dbhost= --dbport= --dbname= --dbusername= --dbpassword= --dbssl= --dbauth= --dbforce] ``` - **strapi new <name>**
@@ -18,16 +18,19 @@ options: [--dev|--debug|--dbclient= --dbhost= --dbport= Generates a new project called **<name>** and creates symlinks for the `./admin` folder and each plugin inside the `./plugin` folder. It means that the Strapi's development workflow has been set up on the machine earlier. - + - **strapi new <name> --debug**
Will display the full error message if one is fired during the database connection. +- **strapi new <name> --quickstart**
+Use the quickstart system to create your all. + - **strapi new <name> --dbclient=<dbclient> --dbhost=<dbhost> --dbport=<dbport> --dbname=<dbname> --dbusername=<dbusername> --dbpassword=<dbpassword> --dbssl=<dbssl> --dbauth=<dbauth> --dbforce**
Generates a new project called **<name>** and skip the interactive database configuration and initilize with these options. - **<dbclient>** can be `mongo`, `postgres`, `mysql`. - **<dbssl>** and **<dbauth>** are available only for `mongo` and are optional. - - **--dbforce** Allows you to overwrite content if the provided database is not empty. Only available for `postgres`, `mysql`, and is optional. + - **--dbforce** Allows you to overwrite content if the provided database is not empty. Only available for `postgres`, `mysql`, and is optional. See the [CONTRIBUTING guide](https://github.com/strapi/strapi/blob/master/CONTRIBUTING.md) for more details. From 56979f692a6c79bff78361284ee2a9816d52189a Mon Sep 17 00:00:00 2001 From: Jim LAURIE Date: Fri, 1 Feb 2019 17:25:04 +0100 Subject: [PATCH 3/3] Fix typo --- docs/3.x.x/cli/CLI.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/3.x.x/cli/CLI.md b/docs/3.x.x/cli/CLI.md index c4d15fa931..20a0c22ae9 100644 --- a/docs/3.x.x/cli/CLI.md +++ b/docs/3.x.x/cli/CLI.md @@ -23,7 +23,7 @@ options: [--dev|--debug|--quickstart|--dbclient= --dbhost= --d Will display the full error message if one is fired during the database connection. - **strapi new <name> --quickstart**
-Use the quickstart system to create your all. +Use the quickstart system to create your app. - **strapi new <name> --dbclient=<dbclient> --dbhost=<dbhost> --dbport=<dbport> --dbname=<dbname> --dbusername=<dbusername> --dbpassword=<dbpassword> --dbssl=<dbssl> --dbauth=<dbauth> --dbforce**