mirror of
https://github.com/strapi/strapi.git
synced 2025-11-09 22:59:14 +00:00
Fix develop mode without TS and refacto strapi-admin file
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
4365796df1
commit
e783e0770a
@ -1,52 +1,16 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const _ = require('lodash');
|
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const WebpackDevServer = require('webpack-dev-server');
|
const WebpackDevServer = require('webpack-dev-server');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const chokidar = require('chokidar');
|
const {
|
||||||
const getWebpackConfig = require('./webpack.config');
|
createCacheDir,
|
||||||
|
getCustomWebpackConfig,
|
||||||
const getPkgPath = name => path.dirname(require.resolve(`${name}/package.json`));
|
shouldBuildAdmin,
|
||||||
|
watchAdminFiles,
|
||||||
const DEFAULT_PLUGINS = [
|
} = require('./utils');
|
||||||
'content-type-builder',
|
|
||||||
'content-manager',
|
|
||||||
'upload',
|
|
||||||
'email',
|
|
||||||
'i18n',
|
|
||||||
'users-permissions',
|
|
||||||
];
|
|
||||||
|
|
||||||
function getCustomWebpackConfig(dir, config) {
|
|
||||||
const adminConfigPath = path.join(dir, 'src', 'admin', 'webpack.config.js');
|
|
||||||
|
|
||||||
let webpackConfig = getWebpackConfig(config);
|
|
||||||
|
|
||||||
if (fs.existsSync(adminConfigPath)) {
|
|
||||||
const webpackAdminConfig = require(path.resolve(adminConfigPath));
|
|
||||||
|
|
||||||
if (_.isFunction(webpackAdminConfig)) {
|
|
||||||
// Expose the devServer configuration
|
|
||||||
if (config.devServer) {
|
|
||||||
webpackConfig.devServer = config.devServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
webpackConfig = webpackAdminConfig(webpackConfig, webpack);
|
|
||||||
|
|
||||||
if (!webpackConfig) {
|
|
||||||
console.error(
|
|
||||||
`${chalk.red('Error:')} Nothing was returned from your custom webpack configuration`
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return webpackConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function build({ plugins, dir, env, options, optimize, forceBuild, useTypeScript }) {
|
async function build({ plugins, dir, env, options, optimize, forceBuild, useTypeScript }) {
|
||||||
const buildAdmin = await shouldBuildAdmin({ dir, plugins, useTypeScript });
|
const buildAdmin = await shouldBuildAdmin({ dir, plugins, useTypeScript });
|
||||||
@ -110,53 +74,6 @@ async function build({ plugins, dir, env, options, optimize, forceBuild, useType
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createPluginsJs(plugins, dest) {
|
|
||||||
const pluginsArray = plugins.map(({ pathToPlugin, name }) => {
|
|
||||||
const shortName = _.camelCase(name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* path.join, on windows, it uses backslashes to resolve path.
|
|
||||||
* The problem is that Webpack does not windows paths
|
|
||||||
* With this tool, we need to rely on "/" and not "\".
|
|
||||||
* This is the reason why '..\\..\\..\\node_modules\\@strapi\\plugin-content-type-builder/strapi-admin.js' was not working.
|
|
||||||
* The regexp at line 105 aims to replace the windows backslashes by standard slash so that webpack can deal with them.
|
|
||||||
* Backslash looks to work only for absolute paths with webpack => https://webpack.js.org/concepts/module-resolution/#absolute-paths
|
|
||||||
*/
|
|
||||||
const realPath = path
|
|
||||||
.join(path.relative(path.resolve(dest, 'admin', 'src'), pathToPlugin), 'strapi-admin.js')
|
|
||||||
.replace(/\\/g, '/');
|
|
||||||
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
pathToPlugin: realPath,
|
|
||||||
shortName,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const content = `
|
|
||||||
${pluginsArray
|
|
||||||
.map(({ pathToPlugin, shortName }) => {
|
|
||||||
const req = `'${pathToPlugin}'`;
|
|
||||||
|
|
||||||
return `import ${shortName} from ${req};`;
|
|
||||||
})
|
|
||||||
.join('\n')}
|
|
||||||
|
|
||||||
|
|
||||||
const plugins = {
|
|
||||||
${[...pluginsArray]
|
|
||||||
.map(({ name, shortName }) => {
|
|
||||||
return ` '${name}': ${shortName},`;
|
|
||||||
})
|
|
||||||
.join('\n')}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default plugins;
|
|
||||||
`;
|
|
||||||
|
|
||||||
return fs.writeFile(path.resolve(dest, 'admin', 'src', 'plugins.js'), content);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function clean({ dir }) {
|
async function clean({ dir }) {
|
||||||
const buildDir = path.join(dir, 'build');
|
const buildDir = path.join(dir, 'build');
|
||||||
const cacheDir = path.join(dir, '.cache');
|
const cacheDir = path.join(dir, '.cache');
|
||||||
@ -165,69 +82,6 @@ async function clean({ dir }) {
|
|||||||
fs.removeSync(cacheDir);
|
fs.removeSync(cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyAdmin(dest) {
|
|
||||||
const adminPath = getPkgPath('@strapi/admin');
|
|
||||||
|
|
||||||
// TODO copy ee folders for plugins
|
|
||||||
await fs.copy(path.resolve(adminPath, 'ee', 'admin'), path.resolve(dest, 'ee', 'admin'));
|
|
||||||
|
|
||||||
await fs.ensureDir(path.resolve(dest, 'config'));
|
|
||||||
await fs.copy(path.resolve(adminPath, 'admin'), path.resolve(dest, 'admin'));
|
|
||||||
|
|
||||||
// Copy package.json
|
|
||||||
await fs.copy(path.resolve(adminPath, 'package.json'), path.resolve(dest, 'package.json'));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createCacheDir({ dir, plugins, useTypeScript }) {
|
|
||||||
const cacheDir = path.resolve(dir, '.cache');
|
|
||||||
|
|
||||||
const pluginsWithFront = Object.keys(plugins)
|
|
||||||
.filter(pluginName => {
|
|
||||||
const pluginInfo = plugins[pluginName];
|
|
||||||
return fs.existsSync(path.resolve(pluginInfo.pathToPlugin, 'strapi-admin.js'));
|
|
||||||
})
|
|
||||||
.map(name => ({ name, ...plugins[name] }));
|
|
||||||
|
|
||||||
// create .cache dir
|
|
||||||
await fs.emptyDir(cacheDir);
|
|
||||||
|
|
||||||
// copy admin core code
|
|
||||||
await copyAdmin(cacheDir);
|
|
||||||
|
|
||||||
// Copy app.js or app.tsx if typescript is enabled
|
|
||||||
const customAdminConfigJSFilePath = path.join(dir, 'src', 'admin', 'app.js');
|
|
||||||
const customAdminConfigTSXFilePath = path.join(dir, 'src', 'admin', 'app.tsx');
|
|
||||||
const customAdminConfigFilePath = useTypeScript
|
|
||||||
? customAdminConfigTSXFilePath
|
|
||||||
: customAdminConfigJSFilePath;
|
|
||||||
|
|
||||||
if (fs.existsSync(customAdminConfigFilePath)) {
|
|
||||||
const defaultAdminConfigFilePath = path.resolve(cacheDir, 'admin', 'src', 'app.js');
|
|
||||||
|
|
||||||
if (useTypeScript) {
|
|
||||||
// Remove the default config file
|
|
||||||
await fs.remove(defaultAdminConfigFilePath);
|
|
||||||
// Copy the custom one
|
|
||||||
await fs.copy(
|
|
||||||
customAdminConfigTSXFilePath,
|
|
||||||
path.resolve(cacheDir, 'admin', 'src', 'app.tsx')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await fs.copy(customAdminConfigFilePath, path.resolve(cacheDir, 'admin', 'src', 'app.js'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy admin extensions folder
|
|
||||||
const adminExtensionFolder = path.join(dir, 'src', 'admin', 'extensions');
|
|
||||||
|
|
||||||
if (fs.existsSync(adminExtensionFolder)) {
|
|
||||||
await fs.copy(adminExtensionFolder, path.resolve(cacheDir, 'admin', 'src', 'extensions'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// create plugins.js with plugins requires
|
|
||||||
await createPluginsJs(pluginsWithFront, cacheDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function watchAdmin({ plugins, dir, host, port, browser, options, useTypeScript }) {
|
async function watchAdmin({ plugins, dir, host, port, browser, options, useTypeScript }) {
|
||||||
// Create the cache dir containing the front-end files.
|
// Create the cache dir containing the front-end files.
|
||||||
const cacheDir = path.join(dir, '.cache');
|
const cacheDir = path.join(dir, '.cache');
|
||||||
@ -297,92 +151,7 @@ async function watchAdmin({ plugins, dir, host, port, browser, options, useTypeS
|
|||||||
|
|
||||||
runServer();
|
runServer();
|
||||||
|
|
||||||
watchFiles(dir, useTypeScript);
|
watchAdminFiles(dir, useTypeScript);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listen to files change and copy the changed files in the .cache/admin folder
|
|
||||||
* when using the dev mode
|
|
||||||
* @param {string} dir
|
|
||||||
*/
|
|
||||||
async function watchFiles(dir, useTypeScript) {
|
|
||||||
const cacheDir = path.join(dir, '.cache');
|
|
||||||
const targetExtensionFile = useTypeScript ? 'app.tsx' : 'app.js';
|
|
||||||
const appExtensionFile = path.join(dir, 'src', 'admin', targetExtensionFile);
|
|
||||||
const extensionsPath = path.join(dir, 'src', 'admin', 'extensions');
|
|
||||||
|
|
||||||
// Only watch the admin/app.js file and the files that are in the ./admin/extensions/folder
|
|
||||||
const filesToWatch = [appExtensionFile, extensionsPath];
|
|
||||||
|
|
||||||
const watcher = chokidar.watch(filesToWatch, {
|
|
||||||
ignoreInitial: true,
|
|
||||||
ignorePermissionErrors: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
watcher.on('all', async (event, filePath) => {
|
|
||||||
const isAppFile = filePath.includes(appExtensionFile);
|
|
||||||
|
|
||||||
// The app.js file needs to be copied in the .cache/admin/src/app.js and the other ones needs to
|
|
||||||
// be copied in the .cache/admin/src/extensions folder
|
|
||||||
const targetPath = isAppFile
|
|
||||||
? path.join(path.normalize(filePath.split(appExtensionFile)[1]), targetExtensionFile)
|
|
||||||
: path.join('extensions', path.normalize(filePath.split(extensionsPath)[1]));
|
|
||||||
|
|
||||||
const destFolder = path.join(cacheDir, 'admin', 'src');
|
|
||||||
|
|
||||||
if (event === 'unlink' || event === 'unlinkDir') {
|
|
||||||
// Remove the file or folder
|
|
||||||
// We need to copy the original files when deleting an override one
|
|
||||||
try {
|
|
||||||
fs.removeSync(path.join(destFolder, targetPath));
|
|
||||||
} catch (err) {
|
|
||||||
console.log('An error occured while deleting the file', err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// In any other case just copy the file into the .cache/admin/src folder
|
|
||||||
try {
|
|
||||||
await fs.copy(filePath, path.join(destFolder, targetPath));
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasCustomAdminCode = async (dir, useTypeScript) => {
|
|
||||||
const customAdminPath = path.join(dir, 'src', 'admin');
|
|
||||||
const customAdminConfigFileExtension = useTypeScript ? 'app.tsx' : 'app.js';
|
|
||||||
const customAdminConfigFile = path.join(customAdminPath, customAdminConfigFileExtension);
|
|
||||||
const customAdminWebpackFile = path.join(customAdminPath, 'webpack.config.js');
|
|
||||||
|
|
||||||
const hasCustomConfigFile = await fs.pathExists(customAdminConfigFile);
|
|
||||||
const hasCustomWebpackFile = await fs.pathExists(customAdminWebpackFile);
|
|
||||||
|
|
||||||
return hasCustomConfigFile || hasCustomWebpackFile;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the project's installed plugins are not the same as a default one.
|
|
||||||
* @param {Object} plugins
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
const hasNonDefaultPlugins = plugins => {
|
|
||||||
// List of plugins that are not the ones installed in a generated app
|
|
||||||
const installedPlugins = Object.keys(plugins).filter(x => !DEFAULT_PLUGINS.includes(x));
|
|
||||||
|
|
||||||
// List of default plugins uninstalled from a generated app
|
|
||||||
const missingPlugins = DEFAULT_PLUGINS.filter(x => !Object.keys(plugins).includes(x));
|
|
||||||
|
|
||||||
const diff = [...installedPlugins, ...missingPlugins];
|
|
||||||
|
|
||||||
return diff.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
async function shouldBuildAdmin({ dir, plugins, useTypeScript }) {
|
|
||||||
const appHasCustomAdminCode = await hasCustomAdminCode(dir, useTypeScript);
|
|
||||||
const appHasNonDefaultPlugins = hasNonDefaultPlugins(plugins);
|
|
||||||
|
|
||||||
return appHasCustomAdminCode || appHasNonDefaultPlugins;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
119
packages/core/admin/utils/create-cache-dir.js
Normal file
119
packages/core/admin/utils/create-cache-dir.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const _ = require('lodash');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
|
const getPkgPath = name => path.dirname(require.resolve(`${name}/package.json`));
|
||||||
|
|
||||||
|
async function createPluginsJs(plugins, dest) {
|
||||||
|
const pluginsArray = plugins.map(({ pathToPlugin, name }) => {
|
||||||
|
const shortName = _.camelCase(name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path.join, on windows, it uses backslashes to resolve path.
|
||||||
|
* The problem is that Webpack does not windows paths
|
||||||
|
* With this tool, we need to rely on "/" and not "\".
|
||||||
|
* This is the reason why '..\\..\\..\\node_modules\\@strapi\\plugin-content-type-builder/strapi-admin.js' was not working.
|
||||||
|
* The regexp at line 105 aims to replace the windows backslashes by standard slash so that webpack can deal with them.
|
||||||
|
* Backslash looks to work only for absolute paths with webpack => https://webpack.js.org/concepts/module-resolution/#absolute-paths
|
||||||
|
*/
|
||||||
|
const realPath = path
|
||||||
|
.join(path.relative(path.resolve(dest, 'admin', 'src'), pathToPlugin), 'strapi-admin.js')
|
||||||
|
.replace(/\\/g, '/');
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
pathToPlugin: realPath,
|
||||||
|
shortName,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = `
|
||||||
|
${pluginsArray
|
||||||
|
.map(({ pathToPlugin, shortName }) => {
|
||||||
|
const req = `'${pathToPlugin}'`;
|
||||||
|
|
||||||
|
return `import ${shortName} from ${req};`;
|
||||||
|
})
|
||||||
|
.join('\n')}
|
||||||
|
|
||||||
|
|
||||||
|
const plugins = {
|
||||||
|
${[...pluginsArray]
|
||||||
|
.map(({ name, shortName }) => {
|
||||||
|
return ` '${name}': ${shortName},`;
|
||||||
|
})
|
||||||
|
.join('\n')}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default plugins;
|
||||||
|
`;
|
||||||
|
|
||||||
|
return fs.writeFile(path.resolve(dest, 'admin', 'src', 'plugins.js'), content);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyAdmin(dest) {
|
||||||
|
const adminPath = getPkgPath('@strapi/admin');
|
||||||
|
|
||||||
|
// TODO copy ee folders for plugins
|
||||||
|
await fs.copy(path.resolve(adminPath, 'ee', 'admin'), path.resolve(dest, 'ee', 'admin'));
|
||||||
|
|
||||||
|
await fs.ensureDir(path.resolve(dest, 'config'));
|
||||||
|
await fs.copy(path.resolve(adminPath, 'admin'), path.resolve(dest, 'admin'));
|
||||||
|
|
||||||
|
// Copy package.json
|
||||||
|
await fs.copy(path.resolve(adminPath, 'package.json'), path.resolve(dest, 'package.json'));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createCacheDir({ dir, plugins, useTypeScript }) {
|
||||||
|
const cacheDir = path.resolve(dir, '.cache');
|
||||||
|
|
||||||
|
const pluginsWithFront = Object.keys(plugins)
|
||||||
|
.filter(pluginName => {
|
||||||
|
const pluginInfo = plugins[pluginName];
|
||||||
|
return fs.existsSync(path.resolve(pluginInfo.pathToPlugin, 'strapi-admin.js'));
|
||||||
|
})
|
||||||
|
.map(name => ({ name, ...plugins[name] }));
|
||||||
|
|
||||||
|
// create .cache dir
|
||||||
|
await fs.emptyDir(cacheDir);
|
||||||
|
|
||||||
|
// copy admin core code
|
||||||
|
await copyAdmin(cacheDir);
|
||||||
|
|
||||||
|
// Copy app.js or app.tsx if typescript is enabled
|
||||||
|
const customAdminConfigJSFilePath = path.join(dir, 'src', 'admin', 'app.js');
|
||||||
|
const customAdminConfigTSXFilePath = path.join(dir, 'src', 'admin', 'app.tsx');
|
||||||
|
const customAdminConfigFilePath = useTypeScript
|
||||||
|
? customAdminConfigTSXFilePath
|
||||||
|
: customAdminConfigJSFilePath;
|
||||||
|
|
||||||
|
if (fs.existsSync(customAdminConfigFilePath)) {
|
||||||
|
const defaultAdminConfigFilePath = path.resolve(cacheDir, 'admin', 'src', 'app.js');
|
||||||
|
|
||||||
|
if (useTypeScript) {
|
||||||
|
// Remove the default config file
|
||||||
|
await fs.remove(defaultAdminConfigFilePath);
|
||||||
|
// Copy the custom one
|
||||||
|
await fs.copy(
|
||||||
|
customAdminConfigTSXFilePath,
|
||||||
|
path.resolve(cacheDir, 'admin', 'src', 'app.tsx')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await fs.copy(customAdminConfigFilePath, path.resolve(cacheDir, 'admin', 'src', 'app.js'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy admin extensions folder
|
||||||
|
const adminExtensionFolder = path.join(dir, 'src', 'admin', 'extensions');
|
||||||
|
|
||||||
|
if (fs.existsSync(adminExtensionFolder)) {
|
||||||
|
await fs.copy(adminExtensionFolder, path.resolve(cacheDir, 'admin', 'src', 'extensions'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// create plugins.js with plugins requires
|
||||||
|
await createPluginsJs(pluginsWithFront, cacheDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = createCacheDir;
|
||||||
38
packages/core/admin/utils/get-custom-webpack-config.js
Normal file
38
packages/core/admin/utils/get-custom-webpack-config.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const _ = require('lodash');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const getWebpackConfig = require('../webpack.config');
|
||||||
|
|
||||||
|
const getCustomWebpackConfig = (dir, config) => {
|
||||||
|
const adminConfigPath = path.join(dir, 'src', 'admin', 'webpack.config.js');
|
||||||
|
|
||||||
|
let webpackConfig = getWebpackConfig(config);
|
||||||
|
|
||||||
|
if (fs.existsSync(adminConfigPath)) {
|
||||||
|
const webpackAdminConfig = require(path.resolve(adminConfigPath));
|
||||||
|
|
||||||
|
if (_.isFunction(webpackAdminConfig)) {
|
||||||
|
// Expose the devServer configuration
|
||||||
|
if (config.devServer) {
|
||||||
|
webpackConfig.devServer = config.devServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
webpackConfig = webpackAdminConfig(webpackConfig, webpack);
|
||||||
|
|
||||||
|
if (!webpackConfig) {
|
||||||
|
console.error(
|
||||||
|
`${chalk.red('Error:')} Nothing was returned from your custom webpack configuration`
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return webpackConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = getCustomWebpackConfig;
|
||||||
13
packages/core/admin/utils/index.js
Normal file
13
packages/core/admin/utils/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const createCacheDir = require('./create-cache-dir');
|
||||||
|
const getCustomWebpackConfig = require('./get-custom-webpack-config');
|
||||||
|
const shouldBuildAdmin = require('./should-build-admin');
|
||||||
|
const watchAdminFiles = require('./watch-admin-files');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createCacheDir,
|
||||||
|
getCustomWebpackConfig,
|
||||||
|
shouldBuildAdmin,
|
||||||
|
watchAdminFiles,
|
||||||
|
};
|
||||||
51
packages/core/admin/utils/should-build-admin.js
Normal file
51
packages/core/admin/utils/should-build-admin.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
|
const DEFAULT_PLUGINS = [
|
||||||
|
'content-type-builder',
|
||||||
|
'content-manager',
|
||||||
|
'upload',
|
||||||
|
'email',
|
||||||
|
'i18n',
|
||||||
|
'users-permissions',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the project's installed plugins are not the same as a default one.
|
||||||
|
* @param {Object} plugins
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
const hasNonDefaultPlugins = plugins => {
|
||||||
|
// List of plugins that are not the ones installed in a generated app
|
||||||
|
const installedPlugins = Object.keys(plugins).filter(x => !DEFAULT_PLUGINS.includes(x));
|
||||||
|
|
||||||
|
// List of default plugins uninstalled from a generated app
|
||||||
|
const missingPlugins = DEFAULT_PLUGINS.filter(x => !Object.keys(plugins).includes(x));
|
||||||
|
|
||||||
|
const diff = [...installedPlugins, ...missingPlugins];
|
||||||
|
|
||||||
|
return diff.length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasCustomAdminCode = async (dir, useTypeScript) => {
|
||||||
|
const customAdminPath = path.join(dir, 'src', 'admin');
|
||||||
|
const customAdminConfigFileExtension = useTypeScript ? 'app.tsx' : 'app.js';
|
||||||
|
const customAdminConfigFile = path.join(customAdminPath, customAdminConfigFileExtension);
|
||||||
|
const customAdminWebpackFile = path.join(customAdminPath, 'webpack.config.js');
|
||||||
|
|
||||||
|
const hasCustomConfigFile = await fs.pathExists(customAdminConfigFile);
|
||||||
|
const hasCustomWebpackFile = await fs.pathExists(customAdminWebpackFile);
|
||||||
|
|
||||||
|
return hasCustomConfigFile || hasCustomWebpackFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
const shouldBuildAdmin = async ({ dir, plugins, useTypeScript }) => {
|
||||||
|
const appHasCustomAdminCode = await hasCustomAdminCode(dir, useTypeScript);
|
||||||
|
const appHasNonDefaultPlugins = hasNonDefaultPlugins(plugins);
|
||||||
|
|
||||||
|
return appHasCustomAdminCode || appHasNonDefaultPlugins;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = shouldBuildAdmin;
|
||||||
56
packages/core/admin/utils/watch-admin-files.js
Normal file
56
packages/core/admin/utils/watch-admin-files.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const chokidar = require('chokidar');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen to files change and copy the changed files in the .cache/admin folder
|
||||||
|
* when using the dev mode
|
||||||
|
* @param {string} dir
|
||||||
|
*/
|
||||||
|
async function watchAdminFiles(dir, useTypeScript) {
|
||||||
|
const cacheDir = path.join(dir, '.cache');
|
||||||
|
const targetExtensionFile = useTypeScript ? 'app.tsx' : 'app.js';
|
||||||
|
const appExtensionFile = path.join(dir, 'src', 'admin', targetExtensionFile);
|
||||||
|
const extensionsPath = path.join(dir, 'src', 'admin', 'extensions');
|
||||||
|
|
||||||
|
// Only watch the admin/app.js file and the files that are in the ./admin/extensions/folder
|
||||||
|
const filesToWatch = [appExtensionFile, extensionsPath];
|
||||||
|
|
||||||
|
const watcher = chokidar.watch(filesToWatch, {
|
||||||
|
ignoreInitial: true,
|
||||||
|
ignorePermissionErrors: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
watcher.on('all', async (event, filePath) => {
|
||||||
|
const isAppFile = filePath.includes(appExtensionFile);
|
||||||
|
|
||||||
|
// The app.js file needs to be copied in the .cache/admin/src/app.js and the other ones needs to
|
||||||
|
// be copied in the .cache/admin/src/extensions folder
|
||||||
|
const targetPath = isAppFile
|
||||||
|
? path.join(path.normalize(filePath.split(appExtensionFile)[1]), targetExtensionFile)
|
||||||
|
: path.join('extensions', path.normalize(filePath.split(extensionsPath)[1]));
|
||||||
|
|
||||||
|
const destFolder = path.join(cacheDir, 'admin', 'src');
|
||||||
|
|
||||||
|
if (event === 'unlink' || event === 'unlinkDir') {
|
||||||
|
// Remove the file or folder
|
||||||
|
// We need to copy the original files when deleting an override one
|
||||||
|
try {
|
||||||
|
fs.removeSync(path.join(destFolder, targetPath));
|
||||||
|
} catch (err) {
|
||||||
|
console.log('An error occured while deleting the file', err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// In any other case just copy the file into the .cache/admin/src folder
|
||||||
|
try {
|
||||||
|
await fs.copy(filePath, path.join(destFolder, targetPath));
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = watchAdminFiles;
|
||||||
@ -28,7 +28,7 @@ module.exports = async function({ build, watchAdmin, polling, browser }) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (cluster.isMaster || cluster.isPrimary) {
|
if (cluster.isMaster || cluster.isPrimary) {
|
||||||
return primaryProcess({ dir, build, browser });
|
return primaryProcess({ dir, build, browser, watchAdmin });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cluster.isWorker) {
|
if (cluster.isWorker) {
|
||||||
|
|||||||
@ -30,7 +30,7 @@ module.exports = async function({ browser }) {
|
|||||||
ee({ dir });
|
ee({ dir });
|
||||||
|
|
||||||
// @convly we need to update this with the real check
|
// @convly we need to update this with the real check
|
||||||
const useTypeScript = true;
|
const useTypeScript = false;
|
||||||
|
|
||||||
strapiAdmin.watchAdmin({
|
strapiAdmin.watchAdmin({
|
||||||
dir,
|
dir,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user