diff --git a/packages/core/admin/.gitignore b/packages/core/admin/.gitignore index 356377047f..e0cbf921c6 100644 --- a/packages/core/admin/.gitignore +++ b/packages/core/admin/.gitignore @@ -9,3 +9,5 @@ yarn-error.log npm-debug.log .idea .env +admin/src/plugins-dev.js +admin/src/plugins.js \ No newline at end of file diff --git a/packages/core/admin/admin/src/index.js b/packages/core/admin/admin/src/index.js index 694d7de2b6..2b19ff70a3 100644 --- a/packages/core/admin/admin/src/index.js +++ b/packages/core/admin/admin/src/index.js @@ -2,6 +2,7 @@ import ReactDOM from 'react-dom'; import { Components, Fields, Middlewares, Reducers } from './core/apis'; import { axiosInstance } from './core/utils'; import appCustomisations from './app'; +// eslint-disable-next-line import/extensions import plugins from './plugins'; import appReducers from './reducers'; diff --git a/packages/core/admin/admin/src/plugins.js b/packages/core/admin/admin/src/plugins.js deleted file mode 100644 index f11d83f2ec..0000000000 --- a/packages/core/admin/admin/src/plugins.js +++ /dev/null @@ -1,22 +0,0 @@ -// // TODO temp file -import documentationPlugin from '../../../../plugins/documentation/admin/src'; -// import graphqlPlugin from '../../../../plugins/graphql/admin/src'; -// import sentryPlugin from '../../../../plugins/sentry/admin/src'; -import i18nPlugin from '../../../../plugins/i18n/strapi-admin'; -import usersPermissionsPlugin from '../../../../plugins/users-permissions/strapi-admin'; -import ctbPlugin from '../../../content-type-builder/strapi-admin'; -import emailPlugin from '../../../email/strapi-admin'; -import uploadPlugin from '../../../upload/strapi-admin'; - -const plugins = { - '@strapi/plugin-content-type-builder': ctbPlugin, - '@strapi/plugin-i18n': i18nPlugin, - '@strapi/plugin-email': emailPlugin, - '@strapi/plugin-upload': uploadPlugin, - '@strapi/plugin-users-permissions': usersPermissionsPlugin, - '@strapi/plugin-documentation': documentationPlugin, - // '@strapi/plugin-graphql': graphqlPlugin, - // '@strapi/plugin-sentry': sentryPlugin, -}; - -export default plugins; diff --git a/packages/core/admin/package.json b/packages/core/admin/package.json index 8ac7a1c413..696dd3f8cc 100644 --- a/packages/core/admin/package.json +++ b/packages/core/admin/package.json @@ -9,8 +9,9 @@ "scripts": { "prepublishOnly": "node ./scripts/build.js", "test": "echo \"no tests yet\"", - "develop": "cross-env NODE_ENV=development webpack serve --config webpack.config.dev.js --progress profile", - "develop:ce": "STRAPI_DISABLE_EE=true webpack serve --config webpack.config.dev.js --progress profile", + "create:plugin-file": "node ./scripts/create-dev-plugins-file.js", + "develop:webpack": "cross-env NODE_ENV=development webpack serve --config webpack.config.dev.js --progress profile", + "develop": "yarn create:plugin-file && yarn develop:webpack", "analyze:bundle": "ANALYZE_BUNDLE=true webpack --config webpack.config.dev.js", "analyze:deps": "ANALYZE_DEPS=true webpack serve --config webpack.config.dev.js --progress profile" }, diff --git a/packages/core/admin/scripts/build.js b/packages/core/admin/scripts/build.js index 04f4e4b00c..664acbeb8f 100644 --- a/packages/core/admin/scripts/build.js +++ b/packages/core/admin/scripts/build.js @@ -3,16 +3,28 @@ const path = require('path'); const webpack = require('webpack'); const webpackConfig = require('../webpack.config'); +const { + getCorePluginsPath, + getPluginToInstallPath, + createPluginsFile, +} = require('./create-plugins-file'); + +const PLUGINS_TO_INSTALL = ['i18n', 'users-permissions']; const buildAdmin = async () => { const entry = path.join(__dirname, '..', 'admin', 'src'); const dest = path.join(__dirname, '..', 'build'); + const corePlugins = getCorePluginsPath(); + const plugins = getPluginToInstallPath(PLUGINS_TO_INSTALL); + const allPlugins = { ...corePlugins, ...plugins }; + + await createPluginsFile(allPlugins); const args = { entry, dest, cacheDir: __dirname, - pluginsPath: [path.resolve(__dirname, '../../../..')], + pluginsPath: [path.resolve(__dirname, '../../../../packages')], env: 'production', optimize: true, options: { diff --git a/packages/core/admin/scripts/create-dev-plugins-file.js b/packages/core/admin/scripts/create-dev-plugins-file.js new file mode 100644 index 0000000000..74d6f50dd1 --- /dev/null +++ b/packages/core/admin/scripts/create-dev-plugins-file.js @@ -0,0 +1,69 @@ +'use strict'; + +const { join, resolve, relative } = require('path'); +const { promisify } = require('util'); +// eslint-disable-next-line node/no-extraneous-require +const glob = promisify(require('glob').glob); +const fs = require('fs-extra'); +const { getCorePluginsPath, createPluginsFile } = require('./create-plugins-file'); + +/** + * Retrieve all plugins that are inside the plugins folder + * @returns Object the plugins + */ +const getPluginsPackages = async () => { + const pathToPackages = resolve(__dirname, '..', '..', '..', 'plugins', '*'); + const pluginsPackageDirs = await glob(pathToPackages); + + return pluginsPackageDirs + .filter(pluginDir => { + return fs.existsSync(join(pluginDir, 'admin', 'src', 'index.js')); + }) + .reduce((acc, current) => { + const depName = current + .replace(/\\/g, '/') + .split('/') + .slice(-1)[0]; + + const adminEntryPoint = join(__dirname, '..', 'admin', 'src'); + + const pathToPlugin = join(relative(adminEntryPoint, current), 'admin', 'src').replace( + /\\/g, + '/' + ); + + acc[depName] = pathToPlugin; + + return acc; + }, {}); +}; + +/** + * Write the plugins.js file or copy the plugins-dev.js file if it exists + */ +const createFile = async () => { + const customPluginFile = join(__dirname, '..', 'admin', 'src', 'plugins-dev.js'); + const pluginFileDest = join(__dirname, '..', 'admin', 'src', 'plugins.js'); + + if (fs.existsSync(customPluginFile)) { + await fs.copy(customPluginFile, pluginFileDest); + + return; + } + + const corePlugins = getCorePluginsPath(); + const plugins = await getPluginsPackages(); + const allPlugins = { ...corePlugins, ...plugins }; + + return createPluginsFile(allPlugins); +}; + +createFile() + .then(() => { + console.log('plugins.js file created'); + process.exit(); + }) + .catch(err => { + console.error(err); + process.exit(1); + }); diff --git a/packages/core/admin/scripts/create-plugins-file.js b/packages/core/admin/scripts/create-plugins-file.js new file mode 100644 index 0000000000..6008ac084f --- /dev/null +++ b/packages/core/admin/scripts/create-plugins-file.js @@ -0,0 +1,92 @@ +'use strict'; + +const { join, resolve, relative } = require('path'); +const { camelCase } = require('lodash'); +const fs = require('fs-extra'); + +const CORE_PLUGINS = ['content-type-builder', 'email', 'upload']; + +/** + * Retrieve the core plugins path + * @returns {Object} + */ +const getCorePluginsPath = () => { + const corePlugins = {}; + + for (const dep of CORE_PLUGINS) { + const packageAdminPath = join(__dirname, '..', '..', dep, 'admin', 'src'); + + const adminEntryPoint = resolve(join(__dirname, '..', 'admin', 'src')); + const pathToPlugin = join(relative(adminEntryPoint, packageAdminPath)).replace(/\\/g, '/'); + + corePlugins[dep] = pathToPlugin; + } + + return corePlugins; +}; + +/** + * Retrieve the plugins real path + * @param {Object[]} pluginsToInstall array of plugins located in the plugins folder + * @returns Object of plugin's paths + */ +const getPluginToInstallPath = pluginsToInstall => { + const plugins = {}; + + for (const dep of pluginsToInstall) { + const packageAdminPath = join(__dirname, '..', '..', '..', 'plugins', dep, 'admin', 'src'); + + const adminEntryPoint = resolve(join(__dirname, '..', 'admin', 'src')); + const pathToPlugin = join(relative(adminEntryPoint, packageAdminPath)).replace(/\\/g, '/'); + + plugins[dep] = pathToPlugin; + } + + return plugins; +}; + +/** + * Write the plugins.js file + * @param {Object} plugins + */ +const createPluginsFile = async plugins => { + const pluginFileDest = resolve(__dirname, '..', 'admin', 'src', 'plugins.js'); + + const allPluginsArray = Object.entries(plugins).map(([plugin, pluginPath]) => { + return { + shortName: camelCase(plugin), + name: plugin, + pluginPath, + }; + }); + + const content = ` +// To override this file create a plugins-dev.js one and copy the content of the plugin.js one. +// When starting the app the script will copy the plugins-dev.js into this one instead. +${allPluginsArray + .map(({ shortName, pluginPath }) => { + const req = `'${pluginPath}'`; + + return `import ${shortName} from ${req};`; + }) + .join('\n')} + +const plugins = { +${[...allPluginsArray] + .map(({ name, shortName }) => { + return ` '${name}': ${shortName},`; + }) + .join('\n')} +}; + +export default plugins; +`; + + return fs.writeFile(pluginFileDest, content); +}; + +module.exports = { + createPluginsFile, + getCorePluginsPath, + getPluginToInstallPath, +};