Commit 666b0d6c authored by lipengcheng 's avatar lipengcheng

github download

parent ef2ea79e
[toc]
#### TODO
- [ ] commander配置多条命令的方式(命令直接对应文件)
- [ ] 显示环境配置信息:nuxt
- [x] 未知的命令给出相关的建议命令
- [x] 通过pkg.engines及semver指定项目的工作环境
- [ ] this.run给仓库做git初始化操作 -- vuecli
#### Q
metalsmith是什么?
handlerbar?
#### program.on()必须在program.parse()之前,因为node的emit()是即时的
#### 未知的命令给出相关的建议命令
通过`program.on('command:*',cb)``leven` 包来实现。-- vuecli
#### 依赖包专门管理 -- vuelci
```javascript
// @vue/cli-shared-utils
[
'env',
'exit',
'ipc',
'logger',
'module',
'object',
'openBrowser',
'pkg',
'pluginResolution',
'launch',
'request',
'spinner',
'validate'
].forEach(m => {
Object.assign(exports, require(`./lib/${m}`))
})
exports.chalk = require('chalk')
exports.execa = require('execa')
exports.semver = require('semver')
Object.defineProperty(exports, 'installedBrowsers', {
enumerable: true,
get () {
return exports.getInstalledBrowsers()
}
})
```
#### 顺序
#### 只包含一个命令的程序
在只包含一个命令的程序中,无需定义处理函数。
```javascript
#!/usr/bin/env node
const { program } = require('commander');
program
.description('An application for pizza ordering')
.option('-p, --peppers', 'Add peppers')
.option('-c, --cheese <type>', 'Add the specified type of cheese', 'marble')
.option('-C, --no-cheese', 'You do not want any cheese');
program.parse();
const options = program.opts();
console.log('you ordered a pizza with:');
if (options.peppers) console.log(' - peppers');
const cheese = !options.cheese ? 'no' : options.cheese;
console.log(' - %s cheese', cheese);
```
#### 工具集
cac: nuxt中使用的命令行工具,类似commander。 -- nuxt
leven: 计算测量两字符串之间的差异,用于对未知的命令给出相关的建议命令 -- vuecli
semver:版本号控制 -- vuelci
slash: 将window反斜杠路径转换为斜杠路径 foo\\bar ➔ foo/bar -- vuecli
minimist:解析参数选项 -- vuecli
validate-npm-package-name:判断作为pkgname的某个字符串是否已经存在
#### 创建项目逻辑
`create .`的话,直接初始化当前目录(以当前目录的文件名为项目名称)
`create xx`,在当前工作目录新建名为`xx`的项目。
xx如果与当前工作目录同名的话,提示用户如何处理?
如果当前目录已经存在同名xx目录的话,提示用户强制覆盖?
#### `path.resolve()`和`path.join()`的区别
一句话,path.join()从左往右,将传入的path片段拼接成一个完成的地址。path.resolve() 从右往左将path片段拼成绝对路径。
#### 可以通过`program.arguments()`方法给顶层命令指定参数
通过.arguments可以为最顶层命令指定命令参数,对子命令而言,参数都包括在.command调用之中了。尖括号(例如<required>)意味着必选,而方括号(例如[optional])则代表可选。可以向.description()方法传递第二个参数,从而在帮助中展示命令参数的信息。该参数是一个包含了 “命令参数名称:命令参数描述” 键值对的对象。
```javascript
program
.arguments('<username> [password]')
.description('test command', {
username: 'user to login',
password: 'password for user, if required'
})
.action((username, password) => {
console.log('username:', username);
console.log('environment:', password || 'no password given');
});
```
#### program.command()的参数
program.command()的第一个参数可以配置**命令名称及命令参数**,参数支持**必选(尖括号表示)****可选(方括号表示)**及变长参数(点号表示,如果使用,只能是最后一个参数)。
```javascript
// 通过绑定处理函数实现命令(这里的指令描述为放在`.command`中)
// 返回新生成的命令(即该子命令)以供继续配置
program
.command('clone <source> [destination]')
.description('clone a repository into a newly created directory')
.action((source, destination) => {
console.log('clone command called');
});
// 通过独立的的可执行文件实现命令 (注意这里指令描述是作为`.command`的第二个参数)
// 返回最顶层的命令以供继续添加子命令
program
.command('start <service>', 'start named service')
.command('stop [service]', 'stop named service, or all if no name supplied');
```
#### 独立的可执行文件规则
**当.command()带有描述参数时,就意味着使用独立的可执行文件作为子命令**。 Commander 将会尝试在入口脚本(例如 ./examples/pm)的目录中搜索program-command形式的可执行文件,例如pm-install, pm-search。通过配置选项executableFile可以自定义名字。
```javascript
program
.version('0.1.0')
.command('install [name]', 'install one or more packages')
.command('search [query]', 'search with optional query')
.command('update', 'update installed packages', { executableFile: 'myUpdateSubCommand' })
.command('list', 'list packages installed', { isDefault: true });
program.parse(process.argv);
```
独立的可执行文件,要么明确`.js`后缀,要么`chmod +x file`赋予执行权限。
#### program.action()处理函数的参数
命令处理函数的参数,为该命令声明的所有参数,除此之外还会附加两个额外参数:一个是解析出的选项,另一个则是该命令对象自身
```javascript
program
.arguments('<name>')
.option('-t, --title <honorific>', 'title to use before name')
.option('-d, --debug', 'display some debugging')
.action((name, options, command) => {
if (options.debug) {
console.error('Called %s with options %o', command.name(), options);
}
const title = options.title ? `${options.title} ` : '';
console.log(`Thank-you ${title}${name}`);
});
```
#### 脚手架执行顺序
- 创建可执行脚本`/bin/cli`
- 配置package.json中的 bin字段
- npm link链接到本地全局环境。npm link --force可以覆盖之前已链接过得同名命令
......@@ -34,5 +191,17 @@ download-git-repo不支持promise
通过util.promisify转换
#### Q
metalsmith是什么?
#### nodejs中操作shell脚本
原生的childProcess
execa
shelljs
cli
#### download-git-repo
download-git-repo内部是通过`download``git-clone``rimraf`几个包实现的
#### npm包download-git-repo 报 'git clone' failed with status 128
[npm包download-git-repo 报 'git clone' failed with status 128 · Issue #17 · wuqiong7/Note](https://github.com/wuqiong7/Note/issues/17)
......@@ -2,14 +2,18 @@
const { program } = require('commander')
const chalk = require('chalk')
const leven = require('leven')
const { checkNodeVersion } = require('../lib/utils')
const PKG = require('../package.json')
checkNodeVersion(PKG.engines.node, PKG.name)
// 配置命令
// 万一重名?添加--force选项强制覆盖
program
.command(`create <app-name>`)
.description(`create a new project`)
.option(`-f, --force`, `overwrite target direcrtory if it exists`)
.action((name, cmd) => {
console.log(`name:`, name);
require('../lib/create.js')(name, cmd)
})
......@@ -17,21 +21,66 @@ program
.command(`config [value]`)
.description(`inspect and modify the config file`)
.option(`-g, --get <path>`, 'get value from option')
.option(`-s, --set <path> <value`)
.option(`-s, --set <path> <value>`)
.option(`-d, --delete <path>`, `delete option from config`)
.action((value, cmd) => {
console.log(`value:`,value);
console.log(`cmd:`,cmd);
})
// 执行独立可执行文件
program
.command('start <service>', 'start named service')
.command('stop [service]', 'stop named service, or all if no name supplied');
program
.version(`lhfe ${require('../package.json').version}`)
.version(`lhfe ${PKG.version}`)
.usage(`<command> [option]`)
program
.on(`--help`, () => console.log(`Run ${chalk.cyan(`lhfe <commadn> -h`)} show details`))
program.on('option:verbose', function () {
console.log(`this.verbose:`,this.verbose);
process.env.VERBOSE = this.verbose;
});
/**
* 未知的命令给出帮助信息及相关命令建议信息
*/
program
.on('command:*', ([cmd]) => {
program.outputHelp()
console.log()
console.log(` ` + chalk.red(`Unknown command ${chalk.yellow(cmd)}`))
suggestCommands(cmd)
process.exitCode = 1
})
// 解析参数
program.parse(process.argv)
\ No newline at end of file
program.parse(process.argv)
// console.log('Options: ', program.opts());
// console.log('Remaining arguments: ', program.args);
/**
* @param unknownCommand 未知的自定义命令
*/
function suggestCommands(unknownCommand) {
const availableCommands = program.commands.map(cmd => cmd._name)
let suggestion = ''
availableCommands.forEach(cmd => {
const isBestMatch = leven(cmd, unknownCommand) < leven(suggestion, unknownCommand)
if (leven(cmd, unknownCommand) < 3 && isBestMatch) {
suggestion = cmd
}
})
if (suggestion) {
console.log(` ` + chalk.red(`Did you mean ${chalk.yellow(suggestion)}?`))
}
}
\ No newline at end of file
#! /usr/bin/env node
console.log('start====');
\ No newline at end of file
#! /usr/bin/env node
console.log('stop====');
\ No newline at end of file
const inquirer = require('inquirer')
const inquirer = require('inquirer')
const { fetchRepoList, fetchTagList } = require('./request')
const { wrapLoading } = require('./utils')
const downlodRepo = require('download-git-repo') //不支持promise
const util = require('util')
const path = require('path')
const ORG = 'zhu-cli'
// const ORG = 'vuejs'
module.exports = class Creator {
constructor(projectname, targetDir){
constructor(projectname, targetDir) {
this.name = projectname
this.target = targetDir
this.downlodRepo = util.promisify(downlodRepo)
}
async fetchRepo(){
let repos = await wrapLoading(fetchRepoList, 'waitgin fetch tempales...')
if(!repos) return;
asyncDownloadRepo(...args){
return new Promise((resolve,reject) => {
download(...args,(err) => {
err ? reject(err) : resolve()
})
})
}
async fetchRepo() {
let repos = await wrapLoading(fetchRepoList, 'Waitting for fetch repo list...')
if (!repos || !Array.isArray(repos)) {
process.exit()
};
repos = repos.map(i => i.name)
const { repo } = await inquirer.prompt([
......@@ -25,13 +38,12 @@ module.exports = class Creator {
message: 'Choose a template'
}
])
console.log(`repo1:`,repo);
return repo
}
async fetchTag(repo) {
let tags = await wrapLoading(fetchTagList, 'waiting fetch tags....', repo)
if(!tags) return ;
let tags = await wrapLoading(fetchTagList, 'Waitting for fetch repo tags....', repo)
if (!tags) return;
tags = tags.map(i => i.name)
const { tag } = await inquirer.prompt([
{
......@@ -44,19 +56,57 @@ module.exports = class Creator {
return tag
}
async download(repo, tag) {
console.log(`repo:`,repo);
console.log(`tag:`,tag);
let requestUrl = `zhu-cli/${repo}${tag ? '#'+tag : ''}`
async exeDownload(repo, tag) {
let requestUrl = `${ORG}/${repo}${tag ? `#${tag}` : ''}`
console.log(`requestUrl:`,requestUrl);
// 优化:先下载到系统目录中(用作缓存),再使用ejs handlerbar渲染模板,然后再写入到目标目录
await this.downlodRepo(requestUrl, path.resolve(process.cwd(), `${repo}@${tag}`))
// await this.downlodRepo(requestUrl, path.resolve(process.cwd(), `${repo}@${tag}`))
await wrapLoading(this.downlodRepo, 'Wating for downloading repo...', requestUrl, path.resolve(process.cwd(), `${repo}@${tag}`))
}
return this.target
async create(type) {
switch (type) {
case 'github':
this.createFromGithub()
break;
default:
this.createFromGitlab()
break;
}
}
async create(){
async createFromGithub() {
const repo = await this.fetchRepo()
const tag = await this.fetchTag(repo)
await this.download(repo, tag)
await this.exeDownload(repo, tag)
// 进入目录安装依赖
}
async createFromGitlab() {
// const url = `direct:https://gitlab.ilaihua.com/laihua-web/laihua-webh5.git` // 会报错git checkout,是git仓库
const url = `direct:https://gitlab.ilaihua.com/laihua-web/laihua-webh5.git#develop` // 没报错,不是git仓库
// const url = `direct:https://gitlab.ilaihua.com/laihua-web/laihua-webh5` // 会报错 是git仓库
// const url = `direct:https://gitlab.ilaihua.com/laihua-web/laihua-webh5#uat` // 没报错,不是git仓库
// const url = `https://gitlab.ilaihua.com:laihua-web/laihua-webh5` // 报错,是git仓库
// const url = `https://gitlab.ilaihua.com:laihua-web/laihua-webh5#uat` // 没报错 不是git仓库
// download(
// url,
// path.resolve(process.cwd(), `aaaa`),
// {
// clone: true,
// // headers: { 'PRIVATE-TOKEN': key }
// },
// function (err) {
// console.log(err || 'Success')
// })
await this.downlodRepo(url, path.resolve(process.cwd(), `aaaa`), { clone: true })
.then(() => { })
.catch((err) => console.log(`err:`, err))
}
}
\ No newline at end of file
......@@ -3,24 +3,48 @@ const path = require('path')
const fs = require('fs-extra');
const inquirer = require('inquirer');
const Creator = require('./Creator')
const { validatePkgName } = require('../lib/utils')
module.exports = async function(projectname, options){
console.log(`projectname:`,projectname);
console.log(`options:`,options);
// 获取命令执行的目录
const cwd = process.cwd()
console.log(`cwd:`, cwd);
// 目标目录
const targetDir = path.join(cwd, projectname)
console.log(`targetDir:`,targetDir);
// path.relative('../', cwd) === path.basename(cwd)
const basename = path.basename(cwd) || path.relative('../', cwd)
let inCurrent = false
if (projectname === basename) {
const { ok } = await inquirer.prompt([
{
name: 'ok',
type: 'confirm',
message: `项目名称与当前工作目录名称一样,是否直接在工作目录初始化项目?`
}
])
inCurrent = ok
} else if (projectname === '.') {
const { ok } = await inquirer.prompt([
{
name: 'ok',
type: 'confirm',
message: `Generate project in current directory?`
}
])
inCurrent = ok
}
const pkbName = inCurrent ? basename : projectname
const targetDir = path.resolve(cwd, inCurrent ? '' : projectname)
if(fs.existsSync(targetDir)){
validatePkgName(pkbName)
// 已存在同名目录
if (!inCurrent && fs.existsSync(targetDir)){
// 有force参数,直接强制删除
// todo: 强制删除前,如果现有目录非空,可以给出提示
// const files = fs.existsSync(outDir) ? fs.readdirSync(outDir) : []
// files.length
if(options.force){
await fs.remove(targetDir)
} else {
// 提示是否要覆盖
console.log('222:',);
const answers = await inquirer.prompt([
{
name: 'action',
......@@ -28,24 +52,36 @@ module.exports = async function(projectname, options){
message: `Target dir has exists`,
choices: [
{ name: 'Overwrite', value: 'overwrite' },
{ name: 'Cncel', value: false},
{ name: 'Cncel', value: false },
]
}
])
console.log(`answers:`,answers);
const {action} = answers
if(!action){
const { action } = answers
if (!action) {
return
} else if(action === 'overwrite'){
console.log('\r\nRemoving:',);
} else if (action === 'overwrite') {
console.log(`\nRemoving ${chalk.cyan(targetDir)}...`)
fs.remove(targetDir)
}
}
}
console.log(`pkbName:`, pkbName);
console.log(`targetDir:`, targetDir);
const { sourceType } = await inquirer.prompt([
{
name: 'sourceType',
type: 'list',
message: `Do u want to create project from Github or Gitlab?`,
choices:[
{name: 'Github', value: 'github'},
{name: 'Gitlab', value: 'gitlab'}
]
}
])
console.log('不存在 开始创建:',);
const creator = new Creator(projectname, targetDir)
console.log(`creator:`,creator);
creator.create()
console.log('开始创建:',);
const creator = new Creator(pkbName, targetDir)
creator.create(sourceType)
}
\ No newline at end of file
const axios = require('axios')
axios.interceptors.response.use(res => res.data)
const ORG = 'zhu-cli'
// const ORG = 'vuejs'
module.exports = {
async fetchRepoList (){
return await axios.get(`https://api.github.com/orgs/zhu-cli/repos`,{
params:{
username: 'slevin57'
}
})
const repoApi = `https://api.github.com/orgs/${ORG}/repos`
const params = { username: 'slevin57' }
return await axios.get(repoApi)
},
async fetchTagList(repo) {
const tagApi = `https://api.github.com/repos/zhu-cli/${repo}/tags`
console.log(`tagApi:`, tagApi);
const tagApi = `https://api.github.com/repos/${ORG}/${repo}/tags`
return await axios.get(tagApi)
},
}
\ No newline at end of file
const ora = require('ora')
const chalk = require('chalk')
const fs = require('fs-extra');
const semver = require('semver')
const exec = require('child_process').exec;
const validateProjectName = require('validate-npm-package-name')
/**
* child_process执行shell
*/
function execute(cmd) {
exec(cmd, function (error, stdout, stderr) {
if (error) {
console.error(error);
}
else {
console.log("success");
}
});
}
// 睡觉方法
async function sleep(ms) {
return new Promise((resolve, rejecrt) => setTimeout(resolve(), ms))
}
/**
*
* @param {*} fn
* @param {*} message
* @param {...any} args
* @returns
*/
async function wrapLoading(fn, message, ...args) {
const spinner = ora(message)
spinner.start()
try {
......@@ -14,13 +42,48 @@ async function wrapLoading(fn, message, ...args) {
return result
} catch (error) {
spinner.fail(`${error}, request failed, refetch...`)
await sleep(5000)
await sleep(3000)
return wrapLoading(fn, message, ...args)
}
}
/**
*
* @param {String} wanted 指定的运行环境版本
* @param {String} id 包名
*/
function checkNodeVersion(wanted, id) {
if (!semver.satisfies(process.version, wanted, { includePrerelease: true })) {
console.log(chalk.red(
'You are using Node ' + process.version + ', but this version of ' + id +
' requires Node ' + wanted + '.\nPlease upgrade your Node version.'
))
process.exit(1)
}
}
/**
* 检查包名/项目名是否可用
* @param {String} name 包/项目名称
*/
function validatePkgName(name) {
const result = validateProjectName(name)
if (!result.validForNewPackages) {
console.error(chalk.red(`Invalid project name: "${name}"`))
result.errors && result.errors.forEach(err => {
console.error(chalk.red.dim('Error: ' + err))
})
result.warnings && result.warnings.forEach(warn => {
console.error(chalk.red.dim('Warning: ' + warn))
})
process.exit(1)
}
}
module.exports = {
sleep,
wrapLoading
wrapLoading,
execute,
checkNodeVersion,
validatePkgName,
}
\ No newline at end of file
......@@ -17,6 +17,14 @@
"download-git-repo": "^3.0.2",
"fs-extra": "^9.1.0",
"inquirer": "^8.0.0",
"ora": "^5.4.0"
"leven": "^3.1.0",
"ora": "^5.4.0",
"semver": "^7.3.5",
"shelljs": "^0.8.4",
"validate-npm-package-name": "^3.0.0"
},
"engines": {
"node": "^12.0.0 || >= 14.0.0",
"npm": ">= 3.0.0"
}
}
......@@ -111,6 +111,11 @@ buffer@^5.2.1, buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
builtins@^1.0.3:
version "1.0.3"
resolved "https://registry.npm.taobao.org/builtins/download/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og=
cacheable-request@^2.1.1:
version "2.1.4"
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d"
......@@ -454,6 +459,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=
get-proxy@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93"
......@@ -479,7 +489,7 @@ git-clone@^0.1.0:
resolved "https://registry.yarnpkg.com/git-clone/-/git-clone-0.1.0.tgz#0d76163778093aef7f1c30238f2a9ef3f07a2eb9"
integrity sha1-DXYWN3gJOu9/HDAjjyqe8/B6Lrk=
glob@^7.1.3:
glob@^7.0.0, glob@^7.1.3:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
......@@ -536,6 +546,13 @@ has-to-string-tag-x@^1.2.0:
dependencies:
has-symbol-support-x "^1.4.1"
has@^1.0.3:
version "1.0.3"
resolved "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=
dependencies:
function-bind "^1.1.1"
http-cache-semantics@3.8.1:
version "3.8.1"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
......@@ -590,6 +607,11 @@ inquirer@^8.0.0:
strip-ansi "^6.0.0"
through "^2.3.6"
interpret@^1.0.0:
version "1.4.0"
resolved "https://registry.npm.taobao.org/interpret/download/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
integrity sha1-Zlq4vE2iendKQFhOgS4+D6RbGh4=
into-stream@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6"
......@@ -598,6 +620,13 @@ into-stream@^3.1.0:
from2 "^2.1.1"
p-is-promise "^1.1.0"
is-core-module@^2.2.0:
version "2.2.0"
resolved "https://registry.npm.taobao.org/is-core-module/download/is-core-module-2.2.0.tgz?cache=0&sync_timestamp=1606411622542&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-core-module%2Fdownload%2Fis-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
integrity sha1-lwN+89UiJNhRY/VZeytj2a/tmBo=
dependencies:
has "^1.0.3"
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
......@@ -672,6 +701,11 @@ keyv@3.0.0:
dependencies:
json-buffer "3.0.0"
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.npm.taobao.org/leven/download/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
integrity sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I=
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
......@@ -695,6 +729,13 @@ lowercase-keys@^1.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.npm.taobao.org/lru-cache/download/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=
dependencies:
yallist "^4.0.0"
make-dir@^1.0.0, make-dir@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
......@@ -819,6 +860,11 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
......@@ -892,6 +938,21 @@ readable-stream@^3.4.0:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
rechoir@^0.6.2:
version "0.6.2"
resolved "https://registry.npm.taobao.org/rechoir/download/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
dependencies:
resolve "^1.1.6"
resolve@^1.1.6:
version "1.20.0"
resolved "https://registry.npm.taobao.org/resolve/download/resolve-1.20.0.tgz?cache=0&sync_timestamp=1613054822645&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU=
dependencies:
is-core-module "^2.2.0"
path-parse "^1.0.6"
responselike@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
......@@ -948,6 +1009,22 @@ seek-bzip@^1.0.5:
dependencies:
commander "^2.8.1"
semver@^7.3.5:
version "7.3.5"
resolved "https://registry.npm.taobao.org/semver/download/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha1-C2Ich5NI2JmOSw5L6Us/EuYBjvc=
dependencies:
lru-cache "^6.0.0"
shelljs@^0.8.4:
version "0.8.4"
resolved "https://registry.npm.taobao.org/shelljs/download/shelljs-0.8.4.tgz?cache=0&sync_timestamp=1607396725654&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fshelljs%2Fdownload%2Fshelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2"
integrity sha1-3naE/ut2f4cWsyYHiooAh1iQ48I=
dependencies:
glob "^7.0.0"
interpret "^1.0.0"
rechoir "^0.6.2"
signal-exit@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
......@@ -1119,6 +1196,13 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
validate-npm-package-name@^3.0.0:
version "3.0.0"
resolved "https://registry.npm.taobao.org/validate-npm-package-name/download/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34=
dependencies:
builtins "^1.0.3"
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
......@@ -1136,6 +1220,11 @@ xtend@^4.0.0:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=
yauzl@^2.4.2:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment