mirror of
https://github.com/strapi/strapi.git
synced 2025-11-04 11:54:10 +00:00
Apply review feedback
Signed-off-by: Rémi de Juvigny <remi@hey.com>
This commit is contained in:
parent
e327d8ccfd
commit
24d42f385f
@ -48,23 +48,42 @@ To create a Strapi template, you need to publish a public GitHub repository that
|
|||||||
|
|
||||||
First, a template's only concern should be to adapt Strapi to a use case. It should not deal with environment-specific configs, like databases, or upload and email providers. This is to make sure that templates stay maintainable, and to avoid conflicts with other CLI options like `--quickstart`.
|
First, a template's only concern should be to adapt Strapi to a use case. It should not deal with environment-specific configs, like databases, or upload and email providers. This is to make sure that templates stay maintainable, and to avoid conflicts with other CLI options like `--quickstart`.
|
||||||
|
|
||||||
Second, a template must follow the following file structure. If any unexpected file or directory is found, the installation will crash.
|
Second, a template must follow the following file structure.
|
||||||
|
|
||||||
### File structure
|
### File structure
|
||||||
|
|
||||||
- `README.md`: to document your template
|
You can add as many files as you want to the root of your template repository. But it must at least have a `template.json` file and a `template` directory.
|
||||||
- `.gitignore`: to remove files from Git
|
|
||||||
- `template.json`: to extend the Strapi app's default `package.json`
|
The `template.json` is used to extend the Strapi app's default `package.json`. You can put all the properties that should overwrite the default `package.json` in a root `package` property. For example, a `template.json` might look like this:
|
||||||
- `/template`: where you can extend the file contents of a Strapi project. All the children are optional
|
|
||||||
- `README.md`: the readme of an app made with this template
|
```json
|
||||||
- `.env.example`: to specify required environment variables
|
{
|
||||||
- `api/`: for collections and single types
|
"package": {
|
||||||
- `components/` for components
|
"dependencies": {
|
||||||
- `config/` can only include the `functions` directory (things like `bootstrap.js` or `404.js`), because other config files are environment-specific.
|
"strapi-plugin-graphql": "latest"
|
||||||
- `data/` to store the data imported by a seed script
|
},
|
||||||
- `plugins/` for custom Strapi plugins
|
"scripts": {
|
||||||
- `public/` to serve files
|
"custom": "node ./scripts/custom.js"
|
||||||
- `scripts/` for custom scripts
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `template` directory is where you can extend the file contents of a Strapi project. All the children are optional, you should only include the files that will overwrite the default Strapi app.
|
||||||
|
|
||||||
|
Only the following contents are allowed inside the `template` directory:
|
||||||
|
|
||||||
|
- `README.md`: the readme of an app made with this template
|
||||||
|
- `.env.example`: to specify required environment variables
|
||||||
|
- `api/`: for collections and single types
|
||||||
|
- `components/` for components
|
||||||
|
- `config/` can only include the `functions` directory (things like `bootstrap.js` or `404.js`), because other config files are environment-specific.
|
||||||
|
- `data/` to store the data imported by a seed script
|
||||||
|
- `plugins/` for custom Strapi plugins
|
||||||
|
- `public/` to serve files
|
||||||
|
- `scripts/` for custom scripts
|
||||||
|
|
||||||
|
If any unexpected file or directory is found, the installation will crash.
|
||||||
|
|
||||||
### Step by step
|
### Step by step
|
||||||
|
|
||||||
@ -73,8 +92,8 @@ After reading the above rules, follow these steps to create your template:
|
|||||||
1. Create a standard Strapi app with `create-strapi-app`, using the `--quickstart` option.
|
1. Create a standard Strapi app with `create-strapi-app`, using the `--quickstart` option.
|
||||||
2. Customize your app to match the needs of your use case.
|
2. Customize your app to match the needs of your use case.
|
||||||
3. Outside of Strapi, create a new directory for your template.
|
3. Outside of Strapi, create a new directory for your template.
|
||||||
4. Create `template.json`, `.gitignore` and `README.md` files in your template directory.
|
4. Create a `template.json` file in your template directory.
|
||||||
5. If you have modified your app's `package.json`, include these changes (and _only_ these changes) in `template.json`. Otherwise, leave it as an empty object.
|
5. If you have modified your app's `package.json`, include these changes (and _only_ these changes) in `template.json` in a `package` property. Otherwise, leave it as an empty object.
|
||||||
6. Create a `/template` subdirectory.
|
6. Create a `/template` subdirectory.
|
||||||
7. Think of all the files you have modified in your app, and copy them to the `/template` directory
|
7. Think of all the files you have modified in your app, and copy them to the `/template` directory
|
||||||
8. Publish the root template project on GitHub. Make sure that the repository is public, and that the code is on the `master` branch.
|
8. Publish the root template project on GitHub. Make sure that the repository is public, and that the code is on the `master` branch.
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
const commander = require('commander');
|
const commander = require('commander');
|
||||||
const packageJson = require('./package.json');
|
const packageJson = require('./package.json');
|
||||||
// TODO: restore this line instead:
|
const generateNewApp = require('strapi-generate-new');
|
||||||
// const generateNewApp = require('strapi-generate-new');
|
|
||||||
const generateNewApp = require('../strapi-generate-new');
|
|
||||||
|
|
||||||
const program = new commander.Command(packageJson.name);
|
const program = new commander.Command(packageJson.name);
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,12 @@ module.exports = async function createProject(scope, { client, connection, depen
|
|||||||
// merge template files if a template is specified
|
// merge template files if a template is specified
|
||||||
const hasTemplate = Boolean(scope.template);
|
const hasTemplate = Boolean(scope.template);
|
||||||
if (hasTemplate) {
|
if (hasTemplate) {
|
||||||
await mergeTemplate(scope.template, rootPath);
|
try {
|
||||||
|
await mergeTemplate(scope.template, rootPath);
|
||||||
|
} catch (error) {
|
||||||
|
await fse.remove(scope.rootPath);
|
||||||
|
stopProcess(`⛔️ Template installation failed: ${error.message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await fse.remove(scope.rootPath);
|
await fse.remove(scope.rootPath);
|
||||||
|
|||||||
@ -3,40 +3,60 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fse = require('fs-extra');
|
const fse = require('fs-extra');
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
const unzip = require('unzip-stream');
|
const tar = require('tar');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const gitInfo = require('hosted-git-info');
|
||||||
|
|
||||||
// Specify all the files and directories a template can have
|
// Specify all the files and directories a template can have
|
||||||
const allowChildren = '*';
|
const allowChildren = '*';
|
||||||
const allowedTemplateTree = {
|
const allowedTemplateContents = {
|
||||||
// Root template files
|
|
||||||
'template.json': true,
|
|
||||||
'README.md': true,
|
'README.md': true,
|
||||||
'.gitignore': true,
|
'.env.example': true,
|
||||||
// Template contents
|
api: allowChildren,
|
||||||
template: {
|
components: allowChildren,
|
||||||
'README.md': true,
|
config: {
|
||||||
'.env.example': true,
|
functions: allowChildren,
|
||||||
api: allowChildren,
|
|
||||||
components: allowChildren,
|
|
||||||
config: {
|
|
||||||
functions: allowChildren,
|
|
||||||
},
|
|
||||||
data: allowChildren,
|
|
||||||
plugins: allowChildren,
|
|
||||||
public: allowChildren,
|
|
||||||
scripts: allowChildren,
|
|
||||||
},
|
},
|
||||||
|
data: allowChildren,
|
||||||
|
plugins: allowChildren,
|
||||||
|
public: allowChildren,
|
||||||
|
scripts: allowChildren,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Make sure the template has the required top-level structure
|
||||||
|
async function checkTemplateRootStructure(templatePath) {
|
||||||
|
// Make sure the root of the repo has a template.json and a template/ folder
|
||||||
|
const templateJsonPath = path.resolve(templatePath, 'template.json');
|
||||||
|
try {
|
||||||
|
const hasTemplateJson = !fse.statSync(templateJsonPath).isDirectory();
|
||||||
|
if (!hasTemplateJson) {
|
||||||
|
throw Error();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw Error(`A template must have a root ${chalk.green('template.json')} file`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the root of the repo has a template.json and a template/ folder
|
||||||
|
const templateDirPath = path.resolve(templatePath, 'template');
|
||||||
|
try {
|
||||||
|
const hasTemplateDir = fse.statSync(templateDirPath).isDirectory();
|
||||||
|
if (!hasTemplateDir) {
|
||||||
|
throw Error();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw Error(`A template must have a root ${chalk.green('template/')} directory`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Traverse template tree to make sure each file and folder is allowed
|
// Traverse template tree to make sure each file and folder is allowed
|
||||||
async function checkTemplateStructure(templatePath) {
|
async function checkTemplateContentsStructure(templateContentsPath) {
|
||||||
// Recursively check if each item in the template is allowed
|
// Recursively check if each item in a directory is allowed
|
||||||
const checkPathContents = (pathToCheck, parents) => {
|
const checkPathContents = (pathToCheck, parents) => {
|
||||||
const contents = fse.readdirSync(pathToCheck);
|
const contents = fse.readdirSync(pathToCheck);
|
||||||
contents.forEach(item => {
|
contents.forEach(item => {
|
||||||
const nextParents = [...parents, item];
|
const nextParents = [...parents, item];
|
||||||
const matchingTreeValue = _.get(allowedTemplateTree, nextParents);
|
const matchingTreeValue = _.get(allowedTemplateContents, nextParents);
|
||||||
|
|
||||||
// Treat files and directories separately
|
// Treat files and directories separately
|
||||||
const itemPath = path.resolve(pathToCheck, item);
|
const itemPath = path.resolve(pathToCheck, item);
|
||||||
@ -44,7 +64,9 @@ async function checkTemplateStructure(templatePath) {
|
|||||||
|
|
||||||
if (matchingTreeValue === undefined) {
|
if (matchingTreeValue === undefined) {
|
||||||
// Unknown paths are forbidden
|
// Unknown paths are forbidden
|
||||||
throw Error(`Illegal template structure, unknown path ${nextParents.join('/')}`);
|
throw Error(
|
||||||
|
`Illegal template structure, unknown path ${chalk.green(nextParents.join('/'))}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchingTreeValue === true) {
|
if (matchingTreeValue === true) {
|
||||||
@ -53,8 +75,8 @@ async function checkTemplateStructure(templatePath) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw Error(
|
throw Error(
|
||||||
`Illegal template structure, expected a file and got a directory at ${nextParents.join(
|
`Illegal template structure, expected a file and got a directory at ${chalk.green(
|
||||||
'/'
|
nextParents.join('/')
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -67,59 +89,60 @@ async function checkTemplateStructure(templatePath) {
|
|||||||
// Check if the contents of the directory are allowed
|
// Check if the contents of the directory are allowed
|
||||||
checkPathContents(itemPath, nextParents);
|
checkPathContents(itemPath, nextParents);
|
||||||
} else {
|
} else {
|
||||||
throw Error(`Illegal template structure, unknow file ${nextParents.join('/')}`);
|
throw Error(
|
||||||
|
`Illegal template structure, unknow file ${chalk.green(nextParents.join('/'))}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
checkPathContents(templatePath, []);
|
checkPathContents(templateContentsPath, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRepoInfo(githubURL) {
|
function getRepoInfo(githubURL) {
|
||||||
|
const { type, user, project } = gitInfo.fromUrl(githubURL);
|
||||||
// Make sure it's a github url
|
// Make sure it's a github url
|
||||||
const address = githubURL.split('://')[1];
|
if (type !== 'github') {
|
||||||
if (!address.startsWith('github.com')) {
|
|
||||||
throw Error('A Strapi template can only be a GitHub URL');
|
throw Error('A Strapi template can only be a GitHub URL');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse github address into parts
|
return { user, project };
|
||||||
const [, username, name, ...rest] = address.split('/');
|
|
||||||
const isRepo = username != null && name != null;
|
|
||||||
if (!isRepo || rest.length > 0) {
|
|
||||||
throw Error('A template URL must be the root of a GitHub repository');
|
|
||||||
}
|
|
||||||
|
|
||||||
return { username, name };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadGithubRepo(repoInfo, rootPath) {
|
async function downloadGithubRepo(repoInfo, templatePath) {
|
||||||
const { username, name, branch = 'master' } = repoInfo;
|
// Download from GitHub
|
||||||
const codeload = `https://codeload.github.com/${username}/${name}/zip/${branch}`;
|
const { user, project } = repoInfo;
|
||||||
const templatePath = path.resolve(rootPath, 'tmp-template');
|
const codeload = `https://codeload.github.com/${user}/${project}/tar.gz/master`;
|
||||||
const response = await fetch(codeload);
|
const response = await fetch(codeload);
|
||||||
await new Promise(resolve => {
|
|
||||||
response.body.pipe(unzip.Extract({ path: templatePath })).on('close', resolve);
|
|
||||||
});
|
|
||||||
|
|
||||||
return templatePath;
|
// Store locally
|
||||||
|
fse.mkdirSync(templatePath);
|
||||||
|
await new Promise(resolve => {
|
||||||
|
response.body.pipe(tar.extract({ strip: 1, cwd: templatePath })).on('close', resolve);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the template's template.json into the Strapi project's package.json
|
// Merge the template's template.json into the Strapi project's package.json
|
||||||
async function mergePackageJSON(rootPath, templatePath, repoInfo) {
|
async function mergePackageJSON(rootPath, templatePath, repoInfo) {
|
||||||
// Import the package.json and template.json templates
|
// Import the package.json and template.json objects
|
||||||
const packageJSON = require(path.resolve(rootPath, 'package.json'));
|
const packageJSON = require(path.resolve(rootPath, 'package.json'));
|
||||||
const templateJSON = require(path.resolve(templatePath, 'template.json'));
|
const templateJSON = require(path.resolve(templatePath, 'template.json'));
|
||||||
|
|
||||||
|
if (!templateJSON.package) {
|
||||||
|
// Nothing to overwrite
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the template.json doesn't overwrite the UUID
|
// Make sure the template.json doesn't overwrite the UUID
|
||||||
if (templateJSON.strapi && templateJSON.strapi.uuid) {
|
if (templateJSON.package.strapi && templateJSON.package.strapi.uuid) {
|
||||||
throw Error('A template cannot overwrite the Strapi UUID');
|
throw Error('A template cannot overwrite the Strapi UUID');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use lodash to deeply merge them
|
// Use lodash to deeply merge them
|
||||||
const mergedConfig = _.merge(packageJSON, templateJSON);
|
const mergedConfig = _.merge(packageJSON, templateJSON.package);
|
||||||
|
|
||||||
// Prefix Strapi UUID with starter info
|
// Prefix Strapi UUID with starter info
|
||||||
const prefix = `STARTER:${repoInfo.username}/${repoInfo.name}:`;
|
const prefix = `STARTER:${repoInfo.user}/${repoInfo.project}:`;
|
||||||
mergedConfig.strapi = {
|
mergedConfig.strapi = {
|
||||||
uuid: prefix + mergedConfig.strapi.uuid,
|
uuid: prefix + mergedConfig.strapi.uuid,
|
||||||
};
|
};
|
||||||
@ -146,19 +169,27 @@ async function mergeFilesAndDirectories(rootPath, templatePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function mergeTemplate(templateUrl, rootPath) {
|
module.exports = async function mergeTemplate(templateUrl, rootPath) {
|
||||||
// Download template repository to a temporary directory
|
// Parse template info
|
||||||
const repoInfo = getRepoInfo(templateUrl);
|
const repoInfo = getRepoInfo(templateUrl);
|
||||||
console.log(`Installing ${repoInfo.username}/${repoInfo.name} template.`);
|
const { user, project } = repoInfo;
|
||||||
const templateParentPath = await downloadGithubRepo(repoInfo, rootPath);
|
console.log(`Installing ${chalk.yellow(`${user}/${project}`)} template.`);
|
||||||
const templatePath = path.resolve(templateParentPath, fse.readdirSync(templateParentPath)[0]);
|
|
||||||
|
// Download template repository to a temporary directory
|
||||||
|
const templatePath = path.resolve(rootPath, '.tmp-template');
|
||||||
|
try {
|
||||||
|
await downloadGithubRepo(repoInfo, templatePath);
|
||||||
|
} catch (error) {
|
||||||
|
throw Error(`Could not download ${chalk.yellow(`${user}/${project}`)} repository`);
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the downloaded template matches the required format
|
// Make sure the downloaded template matches the required format
|
||||||
await checkTemplateStructure(templatePath);
|
await checkTemplateRootStructure(templatePath);
|
||||||
|
await checkTemplateContentsStructure(path.resolve(templatePath, 'template'));
|
||||||
|
|
||||||
// Merge contents of the template in the project
|
// Merge contents of the template in the project
|
||||||
await mergePackageJSON(rootPath, templatePath, repoInfo);
|
await mergePackageJSON(rootPath, templatePath, repoInfo);
|
||||||
await mergeFilesAndDirectories(rootPath, templatePath);
|
await mergeFilesAndDirectories(rootPath, templatePath);
|
||||||
|
|
||||||
// Delete the downloaded template repo
|
// Delete the downloaded template repo
|
||||||
await fse.remove(templateParentPath);
|
await fse.remove(templatePath);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -17,12 +17,13 @@
|
|||||||
"chalk": "^2.4.2",
|
"chalk": "^2.4.2",
|
||||||
"execa": "^1.0.0",
|
"execa": "^1.0.0",
|
||||||
"fs-extra": "^8.0.1",
|
"fs-extra": "^8.0.1",
|
||||||
|
"hosted-git-info": "3.0.5",
|
||||||
"inquirer": "^6.3.1",
|
"inquirer": "^6.3.1",
|
||||||
"lodash": "4.17.19",
|
"lodash": "4.17.19",
|
||||||
"node-fetch": "^1.7.3",
|
"node-fetch": "^1.7.3",
|
||||||
"node-machine-id": "^1.1.10",
|
"node-machine-id": "^1.1.10",
|
||||||
"ora": "^3.4.0",
|
"ora": "^3.4.0",
|
||||||
"unzip-stream": "0.3.0",
|
"tar": "6.0.5",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
72
yarn.lock
72
yarn.lock
@ -4622,14 +4622,6 @@ binary-extensions@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
|
||||||
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
|
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
|
||||||
|
|
||||||
binary@^0.3.0:
|
|
||||||
version "0.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79"
|
|
||||||
integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=
|
|
||||||
dependencies:
|
|
||||||
buffers "~0.1.1"
|
|
||||||
chainsaw "~0.1.0"
|
|
||||||
|
|
||||||
bindings@^1.5.0:
|
bindings@^1.5.0:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||||
@ -4939,11 +4931,6 @@ buffer@^5.1.0:
|
|||||||
base64-js "^1.0.2"
|
base64-js "^1.0.2"
|
||||||
ieee754 "^1.1.4"
|
ieee754 "^1.1.4"
|
||||||
|
|
||||||
buffers@~0.1.1:
|
|
||||||
version "0.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
|
|
||||||
integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s=
|
|
||||||
|
|
||||||
buildmail@3.10.0:
|
buildmail@3.10.0:
|
||||||
version "3.10.0"
|
version "3.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/buildmail/-/buildmail-3.10.0.tgz#c6826d716e7945bb6f6b1434b53985e029a03159"
|
resolved "https://registry.yarnpkg.com/buildmail/-/buildmail-3.10.0.tgz#c6826d716e7945bb6f6b1434b53985e029a03159"
|
||||||
@ -5178,13 +5165,6 @@ ccount@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17"
|
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17"
|
||||||
integrity sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==
|
integrity sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==
|
||||||
|
|
||||||
chainsaw@~0.1.0:
|
|
||||||
version "0.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
|
|
||||||
integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=
|
|
||||||
dependencies:
|
|
||||||
traverse ">=0.3.0 <0.4"
|
|
||||||
|
|
||||||
chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3:
|
chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
||||||
@ -5302,6 +5282,11 @@ chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||||
|
|
||||||
|
chownr@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||||
|
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
||||||
|
|
||||||
chrome-trace-event@^1.0.2:
|
chrome-trace-event@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
|
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
|
||||||
@ -9293,6 +9278,13 @@ homedir-polyfill@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
parse-passwd "^1.0.0"
|
parse-passwd "^1.0.0"
|
||||||
|
|
||||||
|
hosted-git-info@3.0.5:
|
||||||
|
version "3.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.5.tgz#bea87905ef7317442e8df3087faa3c842397df03"
|
||||||
|
integrity sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ==
|
||||||
|
dependencies:
|
||||||
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
|
hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
|
||||||
version "2.8.8"
|
version "2.8.8"
|
||||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||||
@ -12116,6 +12108,13 @@ lru-cache@^5.0.0, lru-cache@^5.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
yallist "^3.0.2"
|
yallist "^3.0.2"
|
||||||
|
|
||||||
|
lru-cache@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||||
|
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||||
|
dependencies:
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
lru_map@^0.3.3:
|
lru_map@^0.3.3:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
|
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
|
||||||
@ -12643,6 +12642,14 @@ minizlib@^2.1.0:
|
|||||||
minipass "^3.0.0"
|
minipass "^3.0.0"
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
|
minizlib@^2.1.1:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||||
|
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||||
|
dependencies:
|
||||||
|
minipass "^3.0.0"
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
mississippi@^3.0.0:
|
mississippi@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
|
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
|
||||||
@ -18134,6 +18141,18 @@ tar-stream@^2.0.0, tar-stream@^2.1.0:
|
|||||||
inherits "^2.0.3"
|
inherits "^2.0.3"
|
||||||
readable-stream "^3.1.1"
|
readable-stream "^3.1.1"
|
||||||
|
|
||||||
|
tar@6.0.5:
|
||||||
|
version "6.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f"
|
||||||
|
integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==
|
||||||
|
dependencies:
|
||||||
|
chownr "^2.0.0"
|
||||||
|
fs-minipass "^2.0.0"
|
||||||
|
minipass "^3.0.0"
|
||||||
|
minizlib "^2.1.1"
|
||||||
|
mkdirp "^1.0.3"
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
|
tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
|
||||||
version "4.4.13"
|
version "4.4.13"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
|
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
|
||||||
@ -18494,11 +18513,6 @@ tr46@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.1"
|
punycode "^2.1.1"
|
||||||
|
|
||||||
"traverse@>=0.3.0 <0.4":
|
|
||||||
version "0.3.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
|
|
||||||
integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=
|
|
||||||
|
|
||||||
tree-kill@^1.2.2:
|
tree-kill@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||||
@ -18849,14 +18863,6 @@ unzip-response@^2.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
|
resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
|
||||||
integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=
|
integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=
|
||||||
|
|
||||||
unzip-stream@0.3.0:
|
|
||||||
version "0.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/unzip-stream/-/unzip-stream-0.3.0.tgz#c30c054cd6b0d64b13a23cd3ece911eb0b2b52d8"
|
|
||||||
integrity sha512-NG1h/MdGIX3HzyqMjyj1laBCmlPYhcO4xEy7gEqqzGiSLw7XqDQCnY4nYSn5XSaH8mQ6TFkaujrO8d/PIZN85A==
|
|
||||||
dependencies:
|
|
||||||
binary "^0.3.0"
|
|
||||||
mkdirp "^0.5.1"
|
|
||||||
|
|
||||||
upath@^1.1.1, upath@^1.2.0:
|
upath@^1.1.1, upath@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
|
resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user