From 3b47457f4f500185665a1fce124d1e6d46bdb243 Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Mon, 12 Aug 2019 15:35:40 +0200 Subject: [PATCH 1/3] make boostrap functions async only --- .../getstarted/config/functions/bootstrap.js | 4 +- .../config/functions/bootstrap.js | 4 +- .../config/functions/bootstrap.js | 32 +++++--- .../config/functions/bootstrap.js | 29 +++---- .../config/functions/bootstrap.js | 12 ++- .../config/functions/bootstrap.js | 32 ++++---- .../config/functions/bootstrap.js | 16 ++-- .../services/UsersPermissions.js | 14 ++-- packages/strapi/lib/Strapi.js | 77 +++++++------------ 9 files changed, 97 insertions(+), 123 deletions(-) diff --git a/examples/getstarted/config/functions/bootstrap.js b/examples/getstarted/config/functions/bootstrap.js index cbb47866f9..917d16f39b 100644 --- a/examples/getstarted/config/functions/bootstrap.js +++ b/examples/getstarted/config/functions/bootstrap.js @@ -8,6 +8,4 @@ * run jobs, or perform some special logic. */ -module.exports = cb => { - cb(); -}; +module.exports = () => {}; diff --git a/packages/strapi-plugin-content-manager/config/functions/bootstrap.js b/packages/strapi-plugin-content-manager/config/functions/bootstrap.js index d9f64e6167..abe7fc32b7 100644 --- a/packages/strapi-plugin-content-manager/config/functions/bootstrap.js +++ b/packages/strapi-plugin-content-manager/config/functions/bootstrap.js @@ -10,8 +10,8 @@ const { /** * Synchronize content manager schemas */ -module.exports = cb => { - syncSchemas().then(() => cb(), err => cb(err)); +module.exports = () => { + return syncSchemas(); }; async function syncSchemas() { diff --git a/packages/strapi-plugin-documentation/config/functions/bootstrap.js b/packages/strapi-plugin-documentation/config/functions/bootstrap.js index 99baa4a916..a1d8ed978d 100755 --- a/packages/strapi-plugin-documentation/config/functions/bootstrap.js +++ b/packages/strapi-plugin-documentation/config/functions/bootstrap.js @@ -2,11 +2,11 @@ const fs = require('fs'); const path = require('path'); const _ = require('lodash'); -module.exports = async cb => { +module.exports = async () => { // Check if the plugin users-permissions is installed because the documentation needs it if (Object.keys(strapi.plugins).indexOf('users-permissions') === -1) { throw new Error( - 'In order to make the documentation plugin works the users-permissions one is required', + 'In order to make the documentation plugin works the users-permissions one is required' ); } @@ -26,16 +26,24 @@ module.exports = async cb => { // Generate plugins' documentation const pluginsWithDocumentationNeeded = services.getPluginsWithDocumentationNeeded(); pluginsWithDocumentationNeeded.forEach(plugin => { - const isDocExisting = services.checkIfPluginDocumentationFolderExists(plugin); + const isDocExisting = services.checkIfPluginDocumentationFolderExists( + plugin + ); if (!isDocExisting) { - services.createDocumentationDirectory(services.getPluginDocumentationPath(plugin)); + services.createDocumentationDirectory( + services.getPluginDocumentationPath(plugin) + ); // create the overrides directory - services.createDocumentationDirectory(services.getPluginOverrideDocumentationPath(plugin)); + services.createDocumentationDirectory( + services.getPluginOverrideDocumentationPath(plugin) + ); services.createPluginDocumentationFile(plugin); shouldUpdateFullDoc = true; } else { - const needToUpdatePluginDoc = services.checkIfPluginDocNeedsUpdate(plugin); + const needToUpdatePluginDoc = services.checkIfPluginDocNeedsUpdate( + plugin + ); if (needToUpdatePluginDoc) { services.createPluginDocumentationFile(plugin); @@ -54,7 +62,9 @@ module.exports = async cb => { // If the documentation directory doesn't exist create it services.createDocumentationDirectory(services.getDocumentationPath(api)); // Create the overrides directory - services.createDocumentationDirectory(services.getDocumentationOverridesPath(api)); + services.createDocumentationDirectory( + services.getDocumentationOverridesPath(api) + ); // Create the documentation files per version services.createDocumentationFile(api); // Then create the {api}.json documentation file shouldUpdateFullDoc = true; @@ -96,7 +106,10 @@ module.exports = async cb => { .sort((a, b) => a - b) .join('.'); }; - const oldDoc = require(path.resolve(documentationPath, 'full_documentation.json')); + const oldDoc = require(path.resolve( + documentationPath, + 'full_documentation.json' + )); const oldDocTags = getDocTagsToString(oldDoc); const currentDocTags = getDocTagsToString(fullDoc); @@ -113,8 +126,7 @@ module.exports = async cb => { fs.writeFileSync( path.resolve(documentationPath, 'full_documentation.json'), JSON.stringify(fullDoc, null, 2), - 'utf8', + 'utf8' ); } - cb(); }; diff --git a/packages/strapi-plugin-email/config/functions/bootstrap.js b/packages/strapi-plugin-email/config/functions/bootstrap.js index 42f0bbcb17..13322ed7df 100644 --- a/packages/strapi-plugin-email/config/functions/bootstrap.js +++ b/packages/strapi-plugin-email/config/functions/bootstrap.js @@ -9,7 +9,7 @@ */ const _ = require('lodash'); -module.exports = async cb => { +module.exports = async () => { // set plugin store const pluginStore = strapi.store({ environment: strapi.config.environment, @@ -27,25 +27,18 @@ module.exports = async cb => { strapi.plugins.email.config.providers.push(require(installedProvider)); } - try { - // if provider config does not exist set one by default - const config = await pluginStore.get({ key: 'provider' }); + // if provider config does not exist set one by default + const config = await pluginStore.get({ key: 'provider' }); - if (!config) { - const provider = _.find(strapi.plugins.email.config.providers, { - provider: 'sendmail', - }); + if (!config) { + const provider = _.find(strapi.plugins.email.config.providers, { + provider: 'sendmail', + }); - const value = _.assign({}, provider, { - // TODO: set other default settings here - }); + const value = _.assign({}, provider, { + // TODO: set other default settings here + }); - await pluginStore.set({ key: 'provider', value }); - } - } catch (err) { - strapi.log.error(err); - strapi.stop(); + await pluginStore.set({ key: 'provider', value }); } - - cb(); }; diff --git a/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js b/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js index 2d69808ae7..d90ec809c6 100644 --- a/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js +++ b/packages/strapi-plugin-settings-manager/config/functions/bootstrap.js @@ -8,20 +8,18 @@ * run jobs, or perform some special logic. */ -module.exports = async cb => { +module.exports = async () => { const pluginStore = strapi.store({ environment: '', - type: 'core' + type: 'core', }); - if (!await pluginStore.get({key: 'application'})) { + if (!(await pluginStore.get({ key: 'application' }))) { const value = { name: 'Default Application', - description: 'This API is going to be awesome!' + description: 'This API is going to be awesome!', }; - await pluginStore.set({key: 'application', value}); + await pluginStore.set({ key: 'application', value }); } - - cb(); }; diff --git a/packages/strapi-plugin-upload/config/functions/bootstrap.js b/packages/strapi-plugin-upload/config/functions/bootstrap.js index d1442fd2fe..b5161cfed9 100644 --- a/packages/strapi-plugin-upload/config/functions/bootstrap.js +++ b/packages/strapi-plugin-upload/config/functions/bootstrap.js @@ -9,7 +9,7 @@ */ const _ = require('lodash'); -module.exports = async cb => { +module.exports = async () => { // set plugin store const pluginStore = strapi.store({ environment: strapi.config.environment, @@ -27,26 +27,20 @@ module.exports = async cb => { strapi.plugins.upload.config.providers.push(require(installedProvider)); } - try { - // if provider config does not exist set one by default - const config = await pluginStore.get({ key: 'provider' }); + // if provider config does not exist set one by default + const config = await pluginStore.get({ key: 'provider' }); - if (!config) { - const provider = _.find(strapi.plugins.upload.config.providers, { - provider: 'local', - }); + if (!config) { + const provider = _.find(strapi.plugins.upload.config.providers, { + provider: 'local', + }); - const value = _.assign({}, provider, { - enabled: true, - // by default limit size to 1 GB - sizeLimit: 1000000, - }); + const value = _.assign({}, provider, { + enabled: true, + // by default limit size to 1 GB + sizeLimit: 1000000, + }); - await pluginStore.set({ key: 'provider', value }); - } - } catch (err) { - strapi.log.error(err); - strapi.stop(); + await pluginStore.set({ key: 'provider', value }); } - cb(); }; diff --git a/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js b/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js index 4fc28d7b26..d3586224ed 100644 --- a/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js +++ b/packages/strapi-plugin-users-permissions/config/functions/bootstrap.js @@ -10,12 +10,16 @@ const _ = require('lodash'); const uuid = require('uuid/v4'); -module.exports = async cb => { +module.exports = async () => { if (!_.get(strapi.plugins['users-permissions'], 'config.jwtSecret')) { const jwtSecret = uuid(); _.set(strapi.plugins['users-permissions'], 'config.jwtSecret', jwtSecret); - await strapi.fs.writePluginFile('users-permissions', 'config/jwt.json', JSON.stringify({ jwtSecret }, null, 2)); + await strapi.fs.writePluginFile( + 'users-permissions', + 'config/jwt.json', + JSON.stringify({ jwtSecret }, null, 2) + ); } const pluginStore = strapi.store({ @@ -144,14 +148,14 @@ module.exports = async cb => { unique_email: true, allow_register: true, email_confirmation: false, - email_confirmation_redirection: `http://${ - strapi.config.currentEnvironment.server.host - }:${strapi.config.currentEnvironment.server.port}/admin`, + email_confirmation_redirection: `http://${strapi.config.currentEnvironment.server.host}:${strapi.config.currentEnvironment.server.port}/admin`, default_role: 'authenticated', }; await pluginStore.set({ key: 'advanced', value }); } - strapi.plugins['users-permissions'].services.userspermissions.initialize(cb); + return strapi.plugins[ + 'users-permissions' + ].services.userspermissions.initialize(); }; diff --git a/packages/strapi-plugin-users-permissions/services/UsersPermissions.js b/packages/strapi-plugin-users-permissions/services/UsersPermissions.js index c267830a01..ac6d79ea0e 100644 --- a/packages/strapi-plugin-users-permissions/services/UsersPermissions.js +++ b/packages/strapi-plugin-users-permissions/services/UsersPermissions.js @@ -462,18 +462,14 @@ module.exports = { return Promise.resolve(); }, - async initialize(cb) { + async initialize() { const roleCount = await strapi.query('role', 'users-permissions').count(); // It has already been initialized. if (roleCount > 0) { - try { - await this.updatePermissions(); - await this.removeDuplicate(); - return cb(); - } catch (err) { - return cb(err); - } + await this.updatePermissions(); + await this.removeDuplicate(); + return; } // Create two first default roles. @@ -490,7 +486,7 @@ module.exports = { }), ]); - this.updatePermissions().then(() => cb(), err => cb(err)); + return this.updatePermissions(); }, async updateRole(roleID, body) { diff --git a/packages/strapi/lib/Strapi.js b/packages/strapi/lib/Strapi.js index 8a5c9c00fe..97d6734c98 100644 --- a/packages/strapi/lib/Strapi.js +++ b/packages/strapi/lib/Strapi.js @@ -366,60 +366,39 @@ class Strapi extends EventEmitter { } async runBootstrapFunctions() { - const execBootstrap = fn => { - if (!fn) return Promise.resolve(); + const timeoutMs = this.config.bootstrapTimeout || 3500; + const warnOnTimeout = () => + setTimeout(() => { + this.log.warn( + `The bootstrap function is taking unusually long to execute (${timeoutMs} miliseconds).` + ); + this.log.warn('Make sure you call it?'); + }, timeoutMs); - return new Promise((resolve, reject) => { - const timeoutMs = this.config.bootstrapTimeout || 3500; - const timer = setTimeout(() => { - this.log.warn( - `The bootstrap function is taking unusually long to execute (${timeoutMs} miliseconds).` - ); - this.log.warn('Make sure you call it?'); - }, timeoutMs); + async function execBootstrap(fn) { + if (!fn) return; - let ranBootstrapFn = false; + const timer = warnOnTimeout(); + try { + await fn(); + } finally { + clearTimeout(timer); + } + } - try { - fn(err => { - if (ranBootstrapFn) { - this.log.error( - 'You called the callback in `strapi.config.boostrap` more than once!' - ); - - return reject(); - } - - ranBootstrapFn = true; - clearTimeout(timer); - - if (err instanceof Error) { - return reject(err); - } - return resolve(err); - }); - } catch (e) { - if (ranBootstrapFn) { - this.log.error( - 'The bootstrap function threw an error after its callback was called.' - ); - - return reject(e); - } - - ranBootstrapFn = true; - clearTimeout(timer); - - return resolve(e); - } + const pluginBoostraps = Object.keys(this.plugins).map(plugin => { + return execBootstrap( + _.get(this.plugins[plugin], 'config.functions.bootstrap') + ).catch(err => { + strapi.log.error(`Bootstrap function in plugin "${plugin}" failed`); + strapi.log.error(err); + strapi.stop(); }); - }; + }); - return Promise.all( - Object.values(this.plugins).map(plugin => - execBootstrap(_.get(plugin, 'config.functions.bootstrap')) - ) - ).then(() => execBootstrap(this.config.functions.bootstrap)); + await Promise.all(pluginBoostraps); + + return execBootstrap(_.get(this.config, ['functions', 'bootstrap'])); } async freeze() { From ac95603a12c5b49e073b019c462ebad714159c5e Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Mon, 12 Aug 2019 15:45:35 +0200 Subject: [PATCH 2/3] Update strapi-generate-new boostrapi function template --- .../lib/resources/files/config/functions/bootstrap.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js b/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js index cbb47866f9..917d16f39b 100644 --- a/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js +++ b/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js @@ -8,6 +8,4 @@ * run jobs, or perform some special logic. */ -module.exports = cb => { - cb(); -}; +module.exports = () => {}; From d9f1f39ee42125dc73501de76e95eae90a79b059 Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Mon, 12 Aug 2019 17:08:22 +0200 Subject: [PATCH 3/3] Add documentation --- .../configurations/configurations.md | 29 ++++++++++++++++++- .../files/config/functions/bootstrap.js | 2 ++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/3.0.0-beta.x/configurations/configurations.md b/docs/3.0.0-beta.x/configurations/configurations.md index 3a614b05d4..2bf143c9cb 100644 --- a/docs/3.0.0-beta.x/configurations/configurations.md +++ b/docs/3.0.0-beta.x/configurations/configurations.md @@ -83,9 +83,36 @@ The `bootstrap` function is called at every server start. You can use it to add Here are some use cases: -- Create an admin user if there isn't. +- Create an admin user if there isn't one. - Fill the database with some necessary data. - Check that the database is up-and-running. +- Load some envrionments variables. + +The bootstrap function can be synchronous or asynchronous + +**Synchronous** + +```js +module.exports = () => { + // some sync code +}; +``` + +**Return a promise** + +```js +module.exports = () => { + return new Promise(/* some code */); +}; +``` + +**Be async** + +```js +module.exports = async () => { + await someSetup(); +}; +``` ### CRON tasks diff --git a/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js b/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js index 917d16f39b..a33be48b92 100644 --- a/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js +++ b/packages/strapi-generate-new/lib/resources/files/config/functions/bootstrap.js @@ -6,6 +6,8 @@ * * This gives you an opportunity to set up your data model, * run jobs, or perform some special logic. + * + * See more details here: https://strapi.io/documentation/3.0.0-beta.x/configurations/configurations.html#bootstrap */ module.exports = () => {};