mirror of
https://github.com/strapi/strapi.git
synced 2025-12-28 15:44:59 +00:00
Merge pull request #4086 from strapi/front/admin-development
Enable easy admin development
This commit is contained in:
commit
893e514a85
@ -29,9 +29,101 @@ By default, the administration panel is exposed via [http://localhost:1337/admin
|
||||
|
||||
The panel will be available through [http://localhost:1337/dashboard](http://localhost:1337/dashboard) with the configurations above.
|
||||
|
||||
---
|
||||
|
||||
### Development mode
|
||||
|
||||
**_Currently not available_**
|
||||
to enable the front-end development mode you need to start your application using the `--watch-admin` flag.
|
||||
|
||||
```bash
|
||||
cd my-app
|
||||
strapi develop --watch-admin
|
||||
```
|
||||
|
||||
With this option you can
|
||||
|
||||
#### Customizing the `strapi-admin` package
|
||||
|
||||
All files added in `my-app/admin/src/` will either be replaced or added
|
||||
|
||||
**Example: Changing the available locales of your application**
|
||||
|
||||
```bash
|
||||
# Create both the admin and admin/src folders
|
||||
cd my-app && mkdir -p admin/src
|
||||
# Change the available locales of the administration panel
|
||||
touch admin/src/i18n.js
|
||||
```
|
||||
|
||||
**Path: `my-app/admin/src/i18n.js**
|
||||
|
||||
```js
|
||||
import { addLocaleData } from 'react-intl';
|
||||
import { reduce } from 'lodash';
|
||||
import en from 'react-intl/locale-data/en';
|
||||
import fr from 'react-intl/locale-data/fr';
|
||||
|
||||
// We dismiss pt-BR and zh-Hans locales since they are not supported by react-intl
|
||||
const locales = {
|
||||
en,
|
||||
fr,
|
||||
};
|
||||
const languages = Object.keys(trads);
|
||||
|
||||
/**
|
||||
* Dynamically generate `translationsMessages object`.
|
||||
*/
|
||||
const translationMessages = reduce(
|
||||
languages,
|
||||
(result, language) => {
|
||||
const obj = result;
|
||||
obj[language] = trads[language];
|
||||
|
||||
if (locales[language]) {
|
||||
addLocaleData(locales[language]);
|
||||
}
|
||||
|
||||
return obj;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
export { languages, translationMessages };
|
||||
```
|
||||
|
||||
> With this modification only English and French will be available in your admin
|
||||
|
||||
#### Customizing a plugin
|
||||
|
||||
Similarly to the back-end override system any file added in `my-app/extensions/<plugin-name>/admin/` will be copied and used instead of the original one (use with care).
|
||||
|
||||
**Example: Changing the current WYSIWYG**
|
||||
|
||||
```bash
|
||||
cd my-app/extensions
|
||||
# Create the content manager folder
|
||||
mkdir content-manager && cd content-manager
|
||||
# Create the admin folder
|
||||
mkdir -p admin/src
|
||||
# Create the components folder and the WysiwygWithErrors one
|
||||
cd admin/src && mkdir -p components/WysiwygWithErrors
|
||||
# Create the index.js so the original file is overridden
|
||||
touch components/WysiwygWithErrors/index.js
|
||||
```
|
||||
|
||||
**Path: `my-app/extensions/content-manager/admin/src/components/WysiwygWithErrors/index.js**
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
import MyNewWYSIWYG from 'my-awesome-lib';
|
||||
|
||||
// This is a dummy example
|
||||
const WysiwygWithErrors = props => <MyNewWYSIWYG {...props} />;
|
||||
|
||||
export default WysiwygWithErrors;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Styles
|
||||
|
||||
@ -47,6 +139,8 @@ To apply your changes you need to rebuild your admin panel
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Logo
|
||||
|
||||
To change the top-left displayed admin panel's logo, add your custom image at `./admin/src/assets/images/logo-strapi.png`.
|
||||
|
||||
@ -37,6 +37,18 @@ Start a Strapi application with autoReload enabled.
|
||||
|
||||
Strapi modifies/creates files at runtime and needs to restart when new files are created. To achieve this, `strapi develop` adds a file watcher and restarts the application when necessary.
|
||||
|
||||
```
|
||||
strapi develop
|
||||
options: [--no-build |--watch-admin ]
|
||||
```
|
||||
|
||||
- **strapi develop**<br/>
|
||||
Starts your application with the autoReload enabled
|
||||
- **strapi develop --no-build**<br/>
|
||||
Starts your application with the autoReload enabled and skip the administration panel build process
|
||||
- **strapi develop --watch-admin**<br/>
|
||||
Starts your application with the autoReload enabled and the front-end development server. It allows you to customize the administration panel.
|
||||
|
||||
::: note
|
||||
You should never use this command to run a Strapi application in production.
|
||||
:::
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
/* eslint-disable no-useless-escape */
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const webpack = require('webpack');
|
||||
const getWebpackConfig = require('./webpack.config.js');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const chalk = require('chalk');
|
||||
const chokidar = require('chokidar');
|
||||
|
||||
const getPkgPath = name =>
|
||||
path.dirname(require.resolve(`${name}/package.json`));
|
||||
@ -135,11 +139,12 @@ async function createCacheDir(dir) {
|
||||
}
|
||||
|
||||
async function build({ dir, env, options }) {
|
||||
const cacheDir = path.resolve(dir, '.cache');
|
||||
// Create the cache dir containing the front-end files.
|
||||
await createCacheDir(dir);
|
||||
|
||||
const cacheDir = path.resolve(dir, '.cache');
|
||||
const entry = path.resolve(cacheDir, 'admin', 'src', 'app.js');
|
||||
const dest = path.resolve(dir, 'build');
|
||||
|
||||
const config = getWebpackConfig({ entry, dest, env, options });
|
||||
|
||||
const compiler = webpack(config);
|
||||
@ -176,8 +181,147 @@ async function build({ dir, env, options }) {
|
||||
});
|
||||
}
|
||||
|
||||
async function watchAdmin({ dir, port, options }) {
|
||||
// Create the cache dir containing the front-end files.
|
||||
await createCacheDir(dir);
|
||||
|
||||
const entry = path.join(dir, '.cache', 'admin', 'src', 'app.js');
|
||||
const dest = path.join(dir, 'build');
|
||||
const env = 'development';
|
||||
|
||||
const args = {
|
||||
entry,
|
||||
dest,
|
||||
env,
|
||||
port,
|
||||
options,
|
||||
};
|
||||
|
||||
const opts = {
|
||||
clientLogLevel: 'silent',
|
||||
hot: true,
|
||||
quiet: true,
|
||||
publicPath: options.publicPath,
|
||||
historyApiFallback: {
|
||||
index: options.publicPath,
|
||||
},
|
||||
};
|
||||
|
||||
const server = new WebpackDevServer(webpack(getWebpackConfig(args)), opts);
|
||||
|
||||
server.listen(port, 'localhost', function(err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
console.log(chalk.green('Starting the development server...'));
|
||||
console.log();
|
||||
console.log(
|
||||
chalk.green(`Admin development at http://localhost:${port}/admin`)
|
||||
);
|
||||
});
|
||||
|
||||
watchFiles(dir);
|
||||
}
|
||||
|
||||
async function watchFiles(dir) {
|
||||
const cacheDir = path.join(dir, '.cache');
|
||||
const pkgJSON = require(path.join(dir, 'package.json'));
|
||||
const admin = path.join(dir, 'admin');
|
||||
|
||||
const appPlugins = Object.keys(pkgJSON.dependencies).filter(
|
||||
dep =>
|
||||
dep.startsWith('strapi-plugin') &&
|
||||
fs.existsSync(path.resolve(getPkgPath(dep), 'admin', 'src', 'index.js'))
|
||||
);
|
||||
const pluginsToWatch = appPlugins.map(plugin =>
|
||||
path.join(
|
||||
dir,
|
||||
'extensions',
|
||||
plugin.replace(/^strapi-plugin-/i, ''),
|
||||
'admin'
|
||||
)
|
||||
);
|
||||
const filesToWatch = [admin, ...pluginsToWatch];
|
||||
|
||||
const watcher = chokidar.watch(filesToWatch, {
|
||||
ignoreInitial: true,
|
||||
ignorePermissionErrors: true,
|
||||
});
|
||||
|
||||
watcher.on('all', async (event, filePath) => {
|
||||
const re = /\/extensions\/([^\/]*)\/.*$/gm;
|
||||
const matched = re.exec(filePath);
|
||||
const isExtension = matched !== null;
|
||||
const pluginName = isExtension ? matched[1] : '';
|
||||
|
||||
const packageName = isExtension
|
||||
? `strapi-plugin-${pluginName}`
|
||||
: 'strapi-admin';
|
||||
const targetPath = isExtension
|
||||
? filePath.split('/extensions/')[1].replace(pluginName, '')
|
||||
: filePath.split('/admin')[1];
|
||||
|
||||
const destFolder = isExtension
|
||||
? path.join(cacheDir, 'plugins', packageName)
|
||||
: path.join(cacheDir, 'admin');
|
||||
|
||||
if (event === 'unlink' || event === 'unlinkDir') {
|
||||
const originalFilePathInNodeModules = path.join(
|
||||
getPkgPath(packageName),
|
||||
isExtension ? '' : 'admin',
|
||||
targetPath
|
||||
);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Check if the file or folder exists in node_modules
|
||||
// If so copy the old one
|
||||
if (fs.pathExistsSync(path.resolve(originalFilePathInNodeModules))) {
|
||||
try {
|
||||
await fs.copy(
|
||||
path.resolve(originalFilePathInNodeModules),
|
||||
path.join(destFolder, targetPath)
|
||||
);
|
||||
|
||||
// The plugins.js file needs to be recreated
|
||||
// when we delete either the admin folder
|
||||
// the admin/src folder
|
||||
// or the plugins.js file
|
||||
// since the path are different when developing inside the monorepository or inside an app
|
||||
const shouldCopyPluginsJSFile =
|
||||
filePath.split('/admin/src').filter(p => !!p).length === 1;
|
||||
|
||||
if (
|
||||
(event === 'unlinkDir' &&
|
||||
!isExtension &&
|
||||
shouldCopyPluginsJSFile) ||
|
||||
(!isExtension && filePath.includes('plugins.js'))
|
||||
) {
|
||||
await createPluginsJs(appPlugins, path.join(cacheDir));
|
||||
}
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In any other case just copy the file into the .cache folder
|
||||
try {
|
||||
await fs.copy(filePath, path.join(destFolder, targetPath));
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
build,
|
||||
createPluginsJs,
|
||||
createCacheDir,
|
||||
watchAdmin,
|
||||
};
|
||||
|
||||
@ -102,6 +102,7 @@
|
||||
"license": "MIT",
|
||||
"gitHead": "c85658a19b8fef0f3164c19693a45db305dc07a9",
|
||||
"devDependencies": {
|
||||
"chokidar": "^3.1.1",
|
||||
"webpack": "^4.40.1",
|
||||
"webpack-cli": "^3.3.2",
|
||||
"webpack-dev-server": "^3.4.1"
|
||||
|
||||
@ -37,12 +37,15 @@ module.exports = ({
|
||||
filename: '[name].[chunkhash].css',
|
||||
chunkFilename: '[name].[chunkhash].chunkhash.css',
|
||||
}),
|
||||
new WebpackBar(),
|
||||
]
|
||||
: [
|
||||
new DuplicatePckgChecker({
|
||||
verbose: true,
|
||||
}),
|
||||
new FriendlyErrorsWebpackPlugin(),
|
||||
new FriendlyErrorsWebpackPlugin({
|
||||
clearConsole: false,
|
||||
}),
|
||||
];
|
||||
|
||||
const scssLoader = isProduction
|
||||
@ -237,7 +240,6 @@ module.exports = ({
|
||||
mainFields: ['browser', 'jsnext:main', 'main'],
|
||||
},
|
||||
plugins: [
|
||||
new WebpackBar(),
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: path.resolve(__dirname, 'index.html'),
|
||||
|
||||
@ -112,6 +112,7 @@ program
|
||||
.command('develop')
|
||||
.alias('dev')
|
||||
.option('--no-build', 'Disable build', false)
|
||||
.option('--watch-admin', 'Enable watch', true)
|
||||
.description('Start your Strapi application in development mode')
|
||||
.action(getLocalScript('develop'));
|
||||
|
||||
@ -190,6 +191,12 @@ program
|
||||
.option('-d, --delete-files', 'Delete files', false)
|
||||
.action(getLocalScript('uninstall'));
|
||||
|
||||
// `$ strapi watch-admin`
|
||||
program
|
||||
.command('watch-admin')
|
||||
.description('Starts the admin dev server')
|
||||
.action(getLocalScript('watchAdmin'));
|
||||
|
||||
/**
|
||||
* Normalize help argument
|
||||
*/
|
||||
|
||||
@ -6,7 +6,7 @@ const _ = require('lodash');
|
||||
const { green, yellow } = require('chalk');
|
||||
const strapiAdmin = require('strapi-admin');
|
||||
const loadConfigFile = require('../load/load-config-files');
|
||||
|
||||
const addSlash = require('../utils/addSlash');
|
||||
/**
|
||||
* `$ strapi build`
|
||||
*/
|
||||
@ -34,9 +34,6 @@ module.exports = async () => {
|
||||
|
||||
console.log(`Building your admin UI with ${green(env)} configuration ...`);
|
||||
|
||||
// Create the .cache folder containing the front-end files
|
||||
await strapiAdmin.createCacheDir(dir);
|
||||
|
||||
return strapiAdmin
|
||||
.build({
|
||||
dir,
|
||||
@ -55,12 +52,3 @@ module.exports = async () => {
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
||||
|
||||
function addSlash(path) {
|
||||
if (typeof path !== 'string') throw new Error('admin.path must be a string');
|
||||
if (path === '' || path === '/') return '/';
|
||||
|
||||
if (path[0] != '/') path = '/' + path;
|
||||
if (path[path.length - 1] != '/') path = path + '/';
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -7,16 +7,18 @@ const chokidar = require('chokidar');
|
||||
const execa = require('execa');
|
||||
|
||||
const { logger } = require('strapi-utils');
|
||||
|
||||
const strapi = require('../index');
|
||||
|
||||
/**
|
||||
* `$ strapi develop`
|
||||
*
|
||||
*/
|
||||
module.exports = async function({ build }) {
|
||||
module.exports = async function({ build, watchAdmin }) {
|
||||
const dir = process.cwd();
|
||||
|
||||
if (build && !fs.existsSync(path.join(dir, 'build'))) {
|
||||
// Don't run the build process if the admin is in watch mode
|
||||
if (build && !watchAdmin && !fs.existsSync(path.join(dir, 'build'))) {
|
||||
try {
|
||||
execa.shellSync('npm run -s build', {
|
||||
stdio: 'inherit',
|
||||
@ -30,6 +32,17 @@ module.exports = async function({ build }) {
|
||||
const strapiInstance = strapi({ dir, autoReload: true });
|
||||
|
||||
if (cluster.isMaster) {
|
||||
// Start the front-end dev server
|
||||
if (watchAdmin) {
|
||||
try {
|
||||
execa('npm', ['run', '-s', 'strapi', 'watch-admin'], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
} catch (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
cluster.on('message', (worker, message) => {
|
||||
switch (message) {
|
||||
case 'reload':
|
||||
|
||||
32
packages/strapi/lib/commands/watchAdmin.js
Normal file
32
packages/strapi/lib/commands/watchAdmin.js
Normal file
@ -0,0 +1,32 @@
|
||||
/* eslint-disable no-useless-escape */
|
||||
const path = require('path');
|
||||
const strapiAdmin = require('strapi-admin');
|
||||
const _ = require('lodash');
|
||||
|
||||
const loadConfigFile = require('../load/load-config-files');
|
||||
const addSlash = require('../utils/addSlash');
|
||||
|
||||
module.exports = async function() {
|
||||
const dir = process.cwd();
|
||||
const envConfigDir = path.join(dir, 'config', 'environments', 'development');
|
||||
const serverConfig = await loadConfigFile(envConfigDir, 'server.+(js|json)');
|
||||
|
||||
const port = _.get(serverConfig, 'port', 1337);
|
||||
const host = _.get(serverConfig, 'host', 'localhost');
|
||||
const adminPort = _.get(serverConfig, 'admin.port', 8000);
|
||||
const adminBackend = _.get(
|
||||
serverConfig,
|
||||
'admin.build.backend',
|
||||
`http://${host}:${port}`
|
||||
);
|
||||
const adminPath = _.get(serverConfig, 'admin.path', '/admin');
|
||||
|
||||
strapiAdmin.watchAdmin({
|
||||
dir,
|
||||
port: adminPort,
|
||||
options: {
|
||||
backend: adminBackend,
|
||||
publicPath: addSlash(adminPath),
|
||||
},
|
||||
});
|
||||
};
|
||||
8
packages/strapi/lib/utils/addSlash.js
Normal file
8
packages/strapi/lib/utils/addSlash.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = path => {
|
||||
if (typeof path !== 'string') throw new Error('admin.path must be a string');
|
||||
if (path === '' || path === '/') return '/';
|
||||
|
||||
if (path[0] != '/') path = '/' + path;
|
||||
if (path[path.length - 1] != '/') path = path + '/';
|
||||
return path;
|
||||
};
|
||||
51
yarn.lock
51
yarn.lock
@ -3095,6 +3095,14 @@ anymatch@^2.0.0:
|
||||
micromatch "^3.1.4"
|
||||
normalize-path "^2.1.1"
|
||||
|
||||
anymatch@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.0.tgz#e609350e50a9313b472789b2f14ef35808ee14d6"
|
||||
integrity sha512-Ozz7l4ixzI7Oxj2+cw+p0tVUt27BpaJ+1+q1TCeANWxHpvyn2+Un+YamBdfKu0uh8xLodGhoa1v7595NhKDAuA==
|
||||
dependencies:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
apollo-cache-control@^0.8.4:
|
||||
version "0.8.4"
|
||||
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.8.4.tgz#a3650d5e4173953e2a3af995bea62147f1ffe4d7"
|
||||
@ -3851,6 +3859,11 @@ binary-extensions@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
||||
integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
|
||||
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
|
||||
|
||||
bindings@^1.3.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||
@ -4018,7 +4031,7 @@ braces@^2.3.1, braces@^2.3.2:
|
||||
split-string "^3.0.2"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
braces@^3.0.1:
|
||||
braces@^3.0.1, braces@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
@ -4541,6 +4554,21 @@ chokidar@^2.0.2, chokidar@^2.1.2, chokidar@^2.1.6:
|
||||
optionalDependencies:
|
||||
fsevents "^1.2.7"
|
||||
|
||||
chokidar@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.1.1.tgz#27e953f3950336efcc455fd03e240c7299062003"
|
||||
integrity sha512-df4o16uZmMHzVQwECZRHwfguOt5ixpuQVaZHjYMvYisgKhE+JXwcj/Tcr3+3bu/XeOJQ9ycYmzu7Mv8XrGxJDQ==
|
||||
dependencies:
|
||||
anymatch "^3.1.0"
|
||||
braces "^3.0.2"
|
||||
glob-parent "^5.0.0"
|
||||
is-binary-path "^2.1.0"
|
||||
is-glob "^4.0.1"
|
||||
normalize-path "^3.0.0"
|
||||
readdirp "^3.1.1"
|
||||
optionalDependencies:
|
||||
fsevents "^2.0.6"
|
||||
|
||||
chownr@^1.1.1, chownr@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6"
|
||||
@ -7721,6 +7749,11 @@ fsevents@^1.2.7:
|
||||
nan "^2.12.1"
|
||||
node-pre-gyp "^0.12.0"
|
||||
|
||||
fsevents@^2.0.6:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.0.7.tgz#382c9b443c6cbac4c57187cdda23aa3bf1ccfc2a"
|
||||
integrity sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==
|
||||
|
||||
fstream@^1.0.0, fstream@^1.0.12:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
|
||||
@ -9379,6 +9412,13 @@ is-binary-path@^1.0.0:
|
||||
dependencies:
|
||||
binary-extensions "^1.0.0"
|
||||
|
||||
is-binary-path@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
|
||||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-bluebird@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-bluebird/-/is-bluebird-1.0.2.tgz#096439060f4aa411abee19143a84d6a55346d6e2"
|
||||
@ -13560,7 +13600,7 @@ pgpass@1.x:
|
||||
dependencies:
|
||||
split "^1.0.0"
|
||||
|
||||
picomatch@^2.0.5:
|
||||
picomatch@^2.0.4, picomatch@^2.0.5:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
|
||||
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
|
||||
@ -15510,6 +15550,13 @@ readdirp@^2.2.1:
|
||||
micromatch "^3.1.10"
|
||||
readable-stream "^2.0.2"
|
||||
|
||||
readdirp@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.1.2.tgz#fa85d2d14d4289920e4671dead96431add2ee78a"
|
||||
integrity sha512-8rhl0xs2cxfVsqzreYCvs8EwBfn/DhVdqtoLmw19uI3SC5avYX9teCurlErfpPXGmYtMHReGaP2RsLnFvz/lnw==
|
||||
dependencies:
|
||||
picomatch "^2.0.4"
|
||||
|
||||
realpath-native@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user