diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md index a180ea2..c30bf2e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,801 @@ # ar-front -> A data mapper framework using in web front. +> An active record style data mapper for web front-end. + +`ar-front` 是一个 ActiveRecord 风格的前端数据层。所谓 ActiveRecord 风格,是指将数据和行为封装在同一个类里。例如,你将得到类似如下的 API 体验: + +```javascript +// 获取所有用户 +const users = await User.list() + +// 遍历数组的数据 +for (const user of users) { + console.log(`User[id=${user.id}, name=${user.name}, age=${user.age}]`) +} + +// 根据 id 获取单条用户数据 +const user = await User.find(1) + +// 创建一条用户数据 +const user = new User({ name: 'James', age: 18 }) +await user.save() + +// 亦可修改 `user` 的值后继续保存 +user.name = 'James Dean' +user.age += 1 +await user.save() +``` + +以上仅是冰山一角,想获得完整的体验请使用 `ar-front` 库。想查看 `ar-front` 是如何在 Vue 项目中简化调用后端 API 的工作,可以参考一个[示例项目](https://github.com/yetrun/vue-todos)。 + +## 目录 + +* [开发理念](#开发理念) +* [安装](#安装) +* [快速上手](#快速上手) +* [使用指南](#使用指南) + * [Model](#model) + * [访问和设置属性](#访问和设置属性) + * [Model.extend](#modelextend) + * [类名称](#类名称) + * [属性](#属性) + * [计算属性](#计算属性) + * [实例方法](#实例方法) + * [actions](#actions) + * [静态方法](#静态方法) + * [onTransform](#ontransform) + * [配置](#配置) + * [混入](#混入) + * [Model.config](#modelconfig) + * [attributes](#attributes) + * [$model](#model-1) + * [Collection](#collection) + * [引入方式](#引入方式) + * [Collection.extend](#collectionextend) + * [model](#model-2) + * [onTransform](#ontransform-1) + * [配置](#配置-1) + * [Collection.config](#collectionconfig) + * [constructor](#constructor) + * [调用数组方法](#调用数组方法) + * [#new](#new) + * [传输](#传输) + * [演示集合资源的派生](#演示集合资源的派生) + * [演示单个资源的派生](#演示单个资源的派生) + * [自定义传输机制](#自定义传输机制) + * [在 Vue 2.x 中使用](#在-vue-2x-中使用) +* [License](#license) + +## 开发理念 + +开篇即介绍开发理念不知火舞,但由于现在的轮子太多了,为避免浪费大家的时间,还是有必要对 `ar-front` 的开发理念做出必要的说明。如果它不是适合你,你就不用考虑它。 + +首先,`ar-front` 库很轻量,它仅仅是将我们平时写接口的方式做了 ActiveRecord 风格的封装。如果你厌倦了 Plain Object 的数据传输方式,可以考虑使用 `ar-front` 将一切数据的行为封装到类里。这样会让你的代码显得更有组织,调用起来也更方便,并且只是增加了一点点的复杂性。 + +其次,`ar-front` 库的更新将会很频繁。由于处于项目开发初期,设计的模式、使用的技术、提供的 API、甚至是库的名称等,都有可能会变动。 + +最后,`ar-front` 不是一个很有野心的库,这意味着你必须清楚 `ar-front` 不能做什么。目前 `ar-front` 尚不能做到的事情有: + +- 它不是一个数据仓库(Store)。 +- 它不支持关系映射(Relation):由于面向的是五花八门的后端接口,前端 API 的关系映射很难有种统一的方法实现。这一点不像面对标准的数据库的时候那样好定义和处理。尽管这样,还是可以在 `ar-front` 中手动定义调用关系的方法,这种硬实现应该也可以满足需要。 +- 目前它还不支持验证(Validation):已经有库支持在表单层面实现验证工作了,如果这能够满足需求,就不再考虑在 `ar-front` 中重复实现了。 +- 目前它还不支持回调(Callbacks):回调看似很有用,但不知道是否真的那么有用。如果不是那么有用,也不考虑在 `ar-front` 中实现了。 + +总之一句话,`ar-front` 只想着如何组织和简化 Web API 的调用,这才是它最适合的应用场景。当然了,如果你的数据交互不是基于 Web API,而是 localStorage、IndexedDB 甚至是内存等,也是它适合的应用场景。 + +## 安装 + +由于当前正在开发中,直接通过 github 仓库获取到最新的稳定开发版: + +```bash +# 使用 yarn +$ yarn add https://github.com/yetrun/ar-front.git + +# 使用 npm +$ npm install --save https://github.com/yetrun/ar-front.git +``` + +## 快速上手 + +假设后端提供操作用户的 Restful API. + +```javascript +const axios = require('axios') +const { Model } = require('ar-front') + +// 定义模型类 +const User = Model.extend({ + // 定义属性 + attributes: { + name: { type: String }, + age: { type: Number } + }, + // 定义行为 + actions: { + async save () { + if (this.id) { + const { data } = await axios.put(`/users/${this.id}`, this.attributes) + this.attributes = data + } else { + const { data } = await axios.post('/users', this.attributes) + this.attributes = data + } + } + }, + static: { + async list () { + const { data } = await axios.get('/users') + return data.map(dataItem => new User(dataItem)) + }, + async find (id) { + const { data } = await axios.get(`/users/${id}`) + return new User(data) + } + } +}) + +// 返回用户列表 +const users = await User.list() + +// 创建用户 +const user = new User() +user.name = 'James' +user.age = 18 +await user.save() + +// 更新用户 +const user = User.find(1) +user.name = 'James Dean' +user.age += 1 +await user.save() +``` + +## 使用指南 + +### Model + +#### 访问和设置属性 + +`ar-front` 最大的优点是直接在对象上设置和返回属性,并能够自动进行类型转换和设置默认值。 + +现有个简单的模型类定义: + +```javascript +const User = Model.extend({ + attributes: { + name: { type: String }, + age: { type: Number, default () { return 18 } } + } +}) +``` + +直接在对象层面访问和设置属性如下: + +``` +const user = new User() + +// 初始化即有默认值 +console.log(user.name) // null +console.log(user.age) // 18 + +// 可通过属性直接在对象层面设置和获取 +user.name = 'Jim' +console.log(user.name) // 'Jim' + +// 自动进行类型转换 +user.age = '18' +console.log(user.age) // 18 +console.log(typeof user.age) // 'number' +``` + +#### `Model.extend` + +```javascript +const { Model } = require('ar-front') + +Model.extend({ + name: '...', + attributes: { /*...*/ }, + computed: { /*...*/ }, + actions: { /*...*/ }, + static: { /*...*/ }, + config: { /*...*/ } +}) +``` + +##### 类名称 + +使用 `name` 定义模型类的名称。 + +示例: + +```javascript +const User = Model.extend({ + name: 'User' +}) + +console.log(User.name) // 'User' +``` + +##### 属性 + +使用 `attributes` 块定义计算属性,可定义属性的类型和默认值。 + +- 类型:支持以下五种类型的定义。除非是 `Object`,否则当设置属性时,自动进行类型转换。 + - Number + - String + - Boolean + - Date + - Array + - Object +- 默认值:可设置常量值或函数,函数绑定的 `this` 是模型实例。 + +示例: + +```javascript +const User = Model.extend({ + attributes: { + name: { type: String }, + age: { type: Number, default: 18 }, + registeredAt: { type: Date, default () { return new Date() }} + } +}) +``` + +##### 计算属性 + +使用 `computed` 块定义计算属性。 + +示例: + +```javascript +const User = Model.extend({ + attributes: { + firstName: { type: String }, + lastName: { type: String } + }, + computed: { + fullName: { + get () { + return this.firstName + ' ' + this.lastName + }, + set (fullName) { + const [firstName, lastName] = fullName.split(' ') + this.firstName = firstName + this.lastName = lastName + } + } + } +}) + +let user = new User({ firstName: 'James', lastName: 'Dean' }) +console.log(user.fullName === 'James Dean') + +user = new User() +user.fullName = 'James Dean' +console.log(user.firstName === 'James') +console.log(user.lastName === 'Dean') +``` + +##### 实例方法 + +使用 `methods` 块定义实例方法。 + +示例: + +```javascript +const User = Model.extend({ + methods: { + getFullName () { + // ... + } + } +}) + +user = new User() +user.getFullName() +``` + +##### `actions` + +使用 `actions` 块定义。`actions` 与 `methods` 不同的是,`methods` 只是纯粹的实例方法,`actions` 调用成功后会自动响应传输机制。我们一般会将 HTTP 调用放在 `actions` 内部。 + +示例: + +```javascript +const User = Model.extend({ + actions: { + async save () { + // ... + } + } +}) + +user = new User() +await user.save() +``` + +##### 静态方法 + +使用 `static` 块定义静态方法。 + +示例: + +```javascript +const User = Model.extend({ + static: { + async find () { + // ... + }, + current () { + // ... + } + } +}) + +await User.find(1) +User.current() +``` + +##### `onTransform` + +自定义收到下游传输时的回调,详细见传输相关的[文档](#传输)。 + +##### 配置 + +使用 `config` 块定义配置。 + +示例: + +```javascript +Model.extend({ + config: { + dynamicAttributes: true, + defineAttributesIn: 'object', + setter: function () { /* ... */ }, + deleter: function () { /* ... */ } + } +}) +``` + +返回:模型类。 + +选项解释: + +- `dynamicAttangributes`:是否支持动态属性,默认为 `false`. 默认情况下,`this.attributes` 只能返回和设置在 `attributes` 块中定义的属性: + + ```javascript + const User = Model.extend({ + attributes: { name: {}, age: {} } + }) + + const user = new User({ name: 'Jim', foo: 'foo' }) + console.log('foo' in user) // false + + user.attributes = { name: 'James', bar: 'bar' } + console.log('bar' in user) // false + ``` + + 而一旦设置 `dynamicAttributes` 为 `true`,则 `this.attributes` 会接受额外的属性。将上面的 Model 定义修改为: + + ```javascript + const User = Model.extend({ + attributes: { name: {}, age: {} }, + config: { dynamicAttributes: true } + }) + ``` + + 则相应的行为将会改变: + + ```javascript + const user = new User({ name: 'Jim', foo: 'foo' }) + console.log('foo' in user) // true + + user.attributes = { name: 'James', bar: 'bar' } + console.log('foo' in user) // false + console.log('bar' in user) // true + ``` + + 设置 `dynamicAttributes` 为 `true` 可以简化定义,例如最简单的设置 Model 的方式可以为: + + ```javascript + const User = Model.extend({ + config: { + dynamicAttributes: true + } + }) + ``` + + 但它的侵入性很大,除非特殊情况,还是建议使用明确声明 `attributes` 的方式。 + +- `defineAttributesIn`:可选值有 `prototype` 和 `object`,默认值是 `prototype`. 它选择将属性的 `getter` 和 `setter` 设置在对象上还是原型上。假设我们设置 Model 为: + + ```javascript + const User = Model.extend({ + attributes: { name: {}, age: {} } + }) + + const user = new User({ name: 'Jim', age: 18 }) + ``` + + 如果设置 `defineAttributesIn` 为 `prototype`,则属性设置在原型上: + + ```javascript + Object.keys(user) // [] + Object.keys(Object.getPrototypeOf(user)) // ['name', 'age'] + ``` + + 反之,如果 `defineAttributesIn` 为 `object`,则属性设置在对象上: + + ```javascript + Object.keys(user) // ['name', 'age'] + Object.keys(Object.getPrototypeOf(user)) // [] + ``` + +- `setter`:自定义设置属性的方式,默认值是类似于下面行为的函数: + + ```javascript + function (key, value) { + this[key] = value + } + ``` + +- `deleter`:自定义删除属性的方式,默认值是类似于下面行为的函数: + + ```javascript + function (key) { + delete this[key] + } + ``` + +##### 混入 + +使用 `mixin` 部分配置混入,示例: + +```javascript +const restfulActions = { + actions: { + update () { /*...*/ }, + destroy () { /*...*/ } + }, + static: { + list () { /*...*/ }, + find (id) { /*...*/ }, + create (attrs) { /*...*/ } + } +} + +Model.extend({ + attributes: { + name: {}, + age: {} + }, + mixin: [ + restfulActions, + // add other mixins + ] +}) +``` + +#### `Model.config` + +返回一个定制新的默认配置的 Model 类。如果你对默认的 Model 配置不满意,可以调用此方法生成一个新的 Model 类。 + +例如下面新生成的 Model 类默认支持动态属性: + +```javascript +const NewModel = Model.config({ + dynamicAttributes: true +}) + +// 新的 Model 类也支持 extend 方法 +const User = NewModel.extend() + +// 可直接使用动态属性 +const user = new User({ name: 'Jim', age: 18 }) +console.log(user.name) // 'Jim' +console.log(user.age) // 18 +``` + +#### `attributes` + +定制 action 是通过 `attributes` 的 setter 和 getter 来实现的。我们还是以下面的模型类定义为例: + +```javascript +const User = Model.extend({ + attributes: { + name: { type: String }, + age: { type: Integer } + } +}) +``` + +首先,可通过构造函数设置属性: + +```javascript +const user = new User({ name: 'Jim', age: 18 ) +``` + +亦可通过 `attributes` 设置器: + +```javascript +const user = new User() +user.attributes = { name: 'Jim', age: 18 } +``` + +`attributes` 的返回器将返回属性的键值对: + +```javascript +user.attributes // { name: 'Jim', age: 18 } +``` + +一般是在定义 action 时使用 `attributes` 的 setter 和 getter,例如一个创建动作,代码实现是: + +```javascript +async create () { + const { data } = await axios.post('/users', this.attributes ) + this.attributes = data +} +``` + +而不是用下面的代码,这样失去了使用 `ar-front` 库的意义了: + +```javascript +async create () { + const { data } = await axios.post('/users', { name: this.name, age: this.age } ) + this.name = data.name + this.age = data.age +} +``` + +`attributes` 的设置会完全覆盖所有属性(它不是更新)。如果你有下面的模型实例: + +```javascript +user = new User({ name: 'Jim' }) +``` + +下面的 `attributes` 覆盖会将 `name` 设置为 `null`: + +```javascript +user.attributes = { age: 18 } + +user.name // null +user.age // 18 +``` + +#### `$model` + +在实例对象上调用 `$model` 方法可返回模型类。 + +示例: + +```javascript +const User = Model.extend({ + name: 'User' +}) + +const user = new User() +console.log(user.$model === User) // true +console.log(user.$model.name) // 'User' +``` + +### Collection + +新添加的 Collection 模块,用来定义集合资源。 + +#### 引入方式 + +```javascript +import { Collection } from 'ar-front' +``` + +#### `Collection.extend` + +定义集合资源的方法,示例: + +```javascript +Collection.extend({ + model: User, + onTransform () { + // ... + }, + config: { + // ... + } +}) +``` + +##### `model` + +`Model.extend` 定义的实例。 + +##### `onTransform` + +自定义收到下游传输时的回调,详细见传输相关的[文档](#传输)。 + +##### 配置 + +当前仅有一个配置选项: + +- `deleter`: 自定义删除集合内索引的行为,默认是如下的函数: + + ```javascript + function deleter (index) { + delete this[index] + } + ``` + +#### `Collection.config` + +生成一个拥有其他默认配置的 Collection 模块,示例: + +```javascript +Collection.config({ + deleter (index) { + Vue.delete(this, index) + } +}) +``` + +#### `constructor` + +构造函数可以传递属性数组,例如: + +```javascript +const Users = Collection.extend({ + model: User +}) + +const users = new Users([ + { id: 1, name: 'Jim', age: 18 }, + { id: 2, name: 'Jane', age: 19 } +]) +``` + +#### 调用数组方法 + +Collection 实例可以调用数组的方法,如 `push`、`splice` 等。 + +#### `#new` + +`new` 方法可以生成一个下游的 Record 实例,例如: + +```javascript +const Users = Collection.extend({ + model: User +}) + +const users = new Users() // users.length === 0 + +const user = users.new({ name: 'Jim', age: 18 }) +await user.save() +// users.length === 1 +``` + +### 传输 + +传输是新引入的机制,其作用是在上游资源与下游资源之间维护一个通道,使得上游资源自动响应下游资源的数据变更。这里有几个重要的概念: + +- 上游资源:可以是 Collection,也可以是 Record +- 下游资源:是上游资源派生出的 Record +- 派生:上游资源生成下游资源,它们之间建立了通道 + +我将用几个例子解释上游资源如何自动响应下游资源的变化。 + +#### 演示集合资源的派生 + +首先,我们定义单个资源和集合资源: + +```javascript +const User = Model.extend({ + attributes: { + id: {}, name: {}, age: {} + }, + actions: { + save () { + // ... + } + } +}) + +const Users = Collection.extend({ + model: User +}) +``` + +然后,我们演示如何由集合资源派生出一个资源: + +```javascript +const users = new Users() +const user = users.new() +``` + +紧接着,更新 `user` 的状态并保存到服务器: + +```javascript +user.attributes = { name: 'Jim', age: 18 } +await user.save() +``` + +最后,展示 `user` 自动添加到 `users` 中: + +```javascript +console.log(users[0] === user) +``` + +#### 演示单个资源的派生 + +单个资源也可派生资源,它用的是 `derive` 方法。下列代码中,`user2` 即为派生出的资源: + +```javascript +const user = new User({ name: 'Jin', age: 18 }) +const user2 = user.derive() +``` + +`user2` 的更新会影响到 `user`,例如: + +```javascript +user2.name = 'Jim' +await user2.save() +console.log(user.name) // 'Jim' +``` + +#### 自定义传输机制 + +默认情况下,集合资源的默认响应行为是自动添加或删除资源,单个资源的默认响应行为是同步属性。自动添加是根据 `id` 属性判断的,自动删除是当资源拥有一个值为 `true` 的 `destroyed` 属性时。 + +如果对默认行为不满意,可以自定义,`Model.extend` 和 `Collection.extend` 都可以传递 `onTransform` 选项: + +```javascript +Model.extend({ + onTransform (downstreamRecord, upstreamRecord) { + // 自定义响应行为 + } +}) + +Collection.extend({ + onTransform (downstreamRecord, upstreamCollection) { + // 自定义响应行为 + } +}) +``` + +### 在 Vue 2.x 中使用 + +我很喜欢 Vue 库,所以当然希望它在 Vue 中能够实现双向绑定。Vue 2.x 曾说过,绑定的对象需要是 Plain Object 的,但其实并不完全是,`ar-front` 库可以很好地在 Vue 中使用,只不过需要结合一些特别的配置。 + +想要在 Vue 2.x 中使用,只需要生成一个新的 Model 类。如下生成一个新的 Model 类并保存在 `model.js` 文件内: + +```javascript +// model.js +import Vue from 'vue' +import { Model } from 'ar-front' + +export default Model.config({ + defineAttributesIn: 'object', + setter (key, value) { + Vue.set(this, key, value) + }, + deleter (key) { + Vue.delete(this, key) + } +}) +``` + +定制模型类时引入 `model.js` 即可: + +```javascript +// user.js +import Model from './model' + +export default Model.extend({ + name: 'User', + attributes: { + // ... + } +}) +``` + +## License + +Apache-2.0 diff --git a/lib/collection.js b/lib/collection.js new file mode 100644 index 0000000..58ce570 --- /dev/null +++ b/lib/collection.js @@ -0,0 +1,153 @@ +// 定义一个集合类,它的元素是 Record +// 集合类首先是一个简易数组,其拥有索引方法、 push 方法等原装数组的方法 +// 集合类然后拥有一个 transformer,其拥有 _transformer 属性和 onTransform 方法 + +const { merge } = require('lodash') +const { Transformer } = require('./transform') + +const appliedArrayMethods = [ + 'concat', + 'copyWithin', + 'entries', + 'every', + 'fill', + 'filter', + 'find', + 'findIndex', + 'flat', + 'flatMap', + 'forEach', + 'includes', + 'indexOf', + 'join', + 'keys', + 'lastIndexOf', + 'map', + 'pop', + 'pop', + 'push', + 'reduce', + 'reduceRight', + 'reverse', + 'shift', + 'slice', + 'some', + 'sort', + 'splice', + 'toLocaleString', + 'toString', + 'unshift', + 'values' +] + +function defineIndex(collection, index) { + Object.defineProperty(collection, index, { + get () { + return this._elems[index] + }, + set (value) { + this._elems[index] = value + }, + configurable: true, + enumerable: true + }) +} + +function applyArrayPrototype (Collection, deleter) { + for (const name of appliedArrayMethods) { + if (!Collection.prototype[name]) { + Collection.prototype[name] = function (...params) { + const previousLength = this.length + + // 首先应用到 this._elems + const result = Array.prototype[name].apply(this._elems, params) + + // 然后调整 Object.defineProperty + if (this.length > previousLength) { + for (let index = previousLength; index < this.length; index++) { + defineIndex(this, index) + } + } else if (this.length < previousLength) { + for (let index = previousLength - 1; index >= this.length; index--) { + deleter.call(this, index) + } + } + + return result + } + } + } +} + +const globalDefaultOptions = { + onTransform (downstreamRecord) { + if (downstreamRecord.destroyed) { + const index = this.findIndex(record => record.id === downstreamRecord.id) + this.splice(index, 1) + } else if(downstreamRecord.id && !this.some(record => record.id === downstreamRecord.id)) { + this.push(downstreamRecord) + } + } +} + +class CollectionFactory { + constructor (defaultConfig = {}) { + this.defaultConfig = defaultConfig + } + + extend (options = {}) { + const { + model, + onTransform, + config: { + deleter + } + } = merge({}, globalDefaultOptions, { config: this.defaultConfig }, options) + + const collectionClass = class Collection { + constructor (items = []) { + Object.defineProperty(this, '_elems', { + value: [], + configurable: true + }) + + // 将 items 关联到自身 + for (const item of items) { + this.push(this.new(item)) + } + } + + get length () { + return this._elems.length + } + + get $model () { + return model + } + + new (attributes) { + const record = new this.$model(attributes) + Object.defineProperty(record, '_transformer', { + value: new Transformer(this, onTransform), + configurable: true + }) + return record + } + } + + applyArrayPrototype(collectionClass, deleter) + + return collectionClass + } + + config (config) { + const defaultConfig = merge({}, this.defaultConfig, config) + return new CollectionFactory(defaultConfig) + } +} + +module.exports = new CollectionFactory({ + deleter (index) { + delete this[index] + } +}) diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..7693d13 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,4 @@ +module.exports = { + Model: require('./model'), + Collection: require('./collection') +} diff --git a/lib/model.js b/lib/model.js new file mode 100644 index 0000000..fe0ddcd --- /dev/null +++ b/lib/model.js @@ -0,0 +1,269 @@ +const { zipObject, merge, isNil, isFunction } = require('lodash') +const { defineTransformer } = require('./transform') + +function convertType (value, type) { + switch (type) { + case String: return isNil(value) ? value : String(value) + case Number: return isNil(value) ? value : Number(value) + case Boolean: return isNil(value) ? value : Boolean(value) + case Date: return isNil(value) ? value : new Date(value) + case Array: return isNil(value) ? value : Array.from(value) + case Object: return value + default: return value + } +} + +function defineAttributes (target, attributesDefinition) { + for (const [field, definition] of Object.entries(attributesDefinition)) { + Object.defineProperty(target, field, { + get () { + return this._attributes[field] + }, + set (value) { + if ('type' in definition) { + value = convertType(value, definition.type) + } + + this._attributes[field] = value + }, + enumerable: true, + configurable: true + }) + } +} + +function defineComputedAttributes (target, attributesDefinition) { + for (const [name, definition] of Object.entries(attributesDefinition)) { + Object.defineProperty(target, name, definition) + } +} + +function defineConstructorAndAttributes ({ defineAttributesIn, attributesDefinition, computedAttributesDefinition }) { + const Model = class { + constructor (attributes = {}, _transformer) { + Object.defineProperty(this, '_attributes', { + value: {}, + configurable: true + }) + + Object.defineProperty(this, '$model', { + value: Model, + configurable: true + }) + + if (defineAttributesIn === 'object') { + defineAttributes(this, attributesDefinition) + defineComputedAttributes(this, computedAttributesDefinition) + } + + this.attributes = attributes + } + } + + if (defineAttributesIn === 'prototype') { + defineAttributes(Model.prototype, attributesDefinition) + defineComputedAttributes(Model.prototype, computedAttributesDefinition) + } + + return Model +} + +function defineAttributesSetterAndGetter (Model, { + dynamicAttributes, + attributesDefinition, + setter, + deleter +}) { + Object.defineProperty(Model.prototype, 'attributes', { + get () { + if (dynamicAttributes) { + const allOwnAttributes = Object.keys(this).reduce((obj, key) => { + if (!key.startsWith('_')) { + obj[key] = this[key] + } + return obj + }, {}) + return Object.assign({}, allOwnAttributes, this._attributes) + } else { + return Object.assign({}, this._attributes) + } + }, + set (attributes) { + // 获得模型定义的默认属性对象 + const defaultAttributes = Object.entries(attributesDefinition).reduce((attrs, [field, definition]) => { + let value = null + if ('default' in definition) { + value = isFunction(definition['default']) ? definition['default'].call(this) : definition['default'] + } + attrs[field] = value + return attrs + }, {}) + + // 获得即将写入的属性对象,此间合并了默认值 + const writingAttributes = dynamicAttributes + ? Object.assign({}, defaultAttributes, attributes) + : Object.keys(defaultAttributes) + .reduce((attrs, field) => { + // 当且仅当 field 不在 attributes 中才适用默认值 + attrs[field] = field in attributes ? attributes[field] : defaultAttributes[field] + return attrs + }, {}) + + // 找出需要删除的属性 + let deletingFields = [] + if (dynamicAttributes) { + // 准备好所有自身的属性 + deletingFields = Object.keys(this) + deletingFields = deletingFields.filter(field => !field.startsWith('_')) + + // 过滤掉即将写入的属性 + deletingFields = new Set(deletingFields) + for (const key of Object.keys(writingAttributes)) { + deletingFields.delete(key) + } + + // 重新转化为数组 + deletingFields = Array.from(deletingFields) + } + + // 写入属性 + for (const [key, value] of Object.entries(writingAttributes)) { + setter.call(this, key, value) + } + + // 删除属性 + for (const key of deletingFields) { + deleter.call(this, key) + } + } + }) +} + +function defineMethods (Model, { actions, methods, staticMethods }) { + // 定义 actions + for (const [name, fn] of Object.entries(actions)) { + if (name in Model.prototype) { + throw new Error(`保留的实例方法:${name}`) + } + + Model.prototype[name] = function (...params) { + const result = fn.apply(this, params) + if (result instanceof Promise) { + return result.then(result => { + this.transform() + return result + }) + } else { + this.transform() + return result + } + } + } + + // 定义 methods + for (const [name, fn] of Object.entries(methods)) { + if (name in Model.prototype) { + throw new Error(`保留的实例方法:${name}`) + } + + Model.prototype[name] = fn + } + + // 定义 static methods + for (const [name, fn] of Object.entries(staticMethods)) { + if (name in Model) { + throw new Error(`保留的静态方法:${name}`) + } + + Model[name] = fn + } +} + +function prepareOptions(options) { + // 整理 attributes、computed、actions、static 部分 + const mixins = options.mixin || [] + const parts = ['attributes', 'computed', 'actions', 'methods', 'static'] + const partDefinitions = parts.map( + part => Object.assign( + {}, + ...mixins.map(m => m[part] || {}), + options[part] || {} + ) + ) + const baseParts = zipObject(parts, partDefinitions) + + // 整理 config 部分 + const configPart = Object.assign({}, this.defaultConfig, options.config || {}) + + // onTransform 是个函数,单独提取 + const onTransform = options.onTransform + + return { + name: options.name || '', // 整理 modelName + config: configPart, + ...baseParts, + onTransform + } +} + +class ModelFactory { + constructor (defaultConfig) { + this.defaultConfig = defaultConfig + } + + extend (options = {}) { + // 调整选项 + options = prepareOptions.call(this, options) + const { + name: modelName, + attributes: attributesDefinition, + computed: computedAttributesDefinition, + actions, + methods, + static: staticMethods, + config: { + dynamicAttributes, + defineAttributesIn, + setter, + deleter + }, + onTransform + } = options + + // 定义类的构造函数、属性和计算属性 + const modelClass = defineConstructorAndAttributes({ defineAttributesIn, attributesDefinition, computedAttributesDefinition }) + + // 设置 modelClass Name + Object.defineProperty(modelClass, 'name', { + value: modelName, + configurable: true + }) + + // 定义 .attributes 方法的 setter 和 getter + defineAttributesSetterAndGetter(modelClass, { dynamicAttributes, attributesDefinition, setter, deleter }) + + // 定义 actions 和 methods + defineMethods(modelClass, { actions, methods, staticMethods }) + + // 定义 Transformer 相关的选项 + defineTransformer(modelClass, { onTransform }) + + return modelClass + } + + config (config) { + const defaultConfig = merge({}, this.defaultConfig, config) + return new ModelFactory(defaultConfig) + } +} + +module.exports = new ModelFactory({ + dynamicAttributes: false, + defineAttributesIn: 'prototype', + setter (key, value) { + this[key] = value + }, + deleter (key) { + delete this[key] + } +}) diff --git a/lib/transform/defineTransformer.js b/lib/transform/defineTransformer.js new file mode 100644 index 0000000..a2ba50c --- /dev/null +++ b/lib/transform/defineTransformer.js @@ -0,0 +1,34 @@ +const Transformer = require('./transformer') + +const defaultOnTransform = function (downstreamRecord) { + this.attributes = downstreamRecord.attributes +} + +module.exports = function defineTransformer (Model, { + onTransform +} = { + onTransform: defaultOnTransform +}) { + // 定义 derive 方法 + Object.defineProperty(Model.prototype, 'derive', { + value () { + const record = new Model(this.attributes) + Object.defineProperty(record, '_transformer', { + value: new Transformer(this, onTransform || defaultOnTransform), + configurable: true + }) + return record + }, + configurable: true + }) + + // 定义 transform 方法 + Object.defineProperty(Model.prototype, 'transform', { + value (attributes) { + if (this._transformer) { + this._transformer.transform(this) + } + }, + configurable: true + }) +} diff --git a/lib/transform/index.js b/lib/transform/index.js new file mode 100644 index 0000000..d3e2d44 --- /dev/null +++ b/lib/transform/index.js @@ -0,0 +1,2 @@ +exports.Transformer = require('./transformer') +exports.defineTransformer = require('./defineTransformer') diff --git a/lib/transform/transformer.js b/lib/transform/transformer.js new file mode 100644 index 0000000..7c60c87 --- /dev/null +++ b/lib/transform/transformer.js @@ -0,0 +1,14 @@ +class Transformer { + constructor (upstreamRecord, onTransform) { + this._upstreamRecord = upstreamRecord + this._onTransform = onTransform + } + + transform (downstreamRecord) { + if (this._onTransform) { + this._onTransform.call(this._upstreamRecord, downstreamRecord, this._upstreamRecord) + } + } +} + +module.exports = Transformer diff --git a/package.json b/package.json index 901307b..af79511 100644 --- a/package.json +++ b/package.json @@ -5,5 +5,19 @@ "main": "lib/index.js", "repository": "https://github.com/yetrun/ar-front", "author": "yetrun", - "license": "Apache-2.0" + "license": "Apache-2.0", + "scripts": { + "test": "ava" + }, + "ava": { + "files": [ + "test/**/*.test.js" + ] + }, + "devDependencies": { + "ava": "^3.15.0" + }, + "dependencies": { + "lodash": "^4.17.21" + } } diff --git a/test/attributeTypes.test.js b/test/attributeTypes.test.js new file mode 100644 index 0000000..b5884bc --- /dev/null +++ b/test/attributeTypes.test.js @@ -0,0 +1,82 @@ +const test = require('ava') +const Model = require('../lib/model') + +const User = Model.extend({ + attributes: { + name: { type: String }, + age: { type: Number } + } +}) + +const TypesModel = Model.extend({ + attributes: { + aString: { type: String }, + aNumber: { type: Number }, + aBoolean: { type: Boolean }, + aDate: { type: Date }, + anArray: { type: Array }, + anObject: { type: Object } + } +}) + +test('string is not number', t => { + t.not('18', 18) +}) + +test('convert types in constructor', t => { + const user = new User({ name: 'Jim', age: '18' }) + + t.is(user.name, 'Jim') + t.is(user.age, 18) +}) + +test('convert types in .attributes method', t => { + const user = new User() + user.attributes = { name: 'Jim', age: '18' } + + t.is(user.name, 'Jim') + t.is(user.age, 18) +}) + +test('convert types in setter', t => { + const user = new User() + user.name = 'Jim' + user.age = '18' + + t.is(user.name, 'Jim') + t.is(user.age, 18) +}) + +test('not convert undefined', t => { + const model = new TypesModel({ + aString: undefined, + aNumber: undefined, + aBoolean: undefined, + aDate: undefined, + anArray: undefined, + anObject: undefined, + }) + t.is(model.aString, undefined) + t.is(model.aNumber, undefined) + t.is(model.aBoolean, undefined) + t.is(model.aDate, undefined) + t.is(model.anArray, undefined) + t.is(model.anObject, undefined) +}) + +test('not convert null', t => { + const model = new TypesModel({ + aString: null, + aNumber: null, + aBoolean: null, + aDate: null, + anArray: null, + anObject: null, + }) + t.is(model.aString, null) + t.is(model.aNumber, null) + t.is(model.aBoolean, null) + t.is(model.aDate, null) + t.is(model.anArray, null) + t.is(model.anObject, null) +}) diff --git a/test/attributesConfig/README.md b/test/attributesConfig/README.md new file mode 100644 index 0000000..16dc5ec --- /dev/null +++ b/test/attributesConfig/README.md @@ -0,0 +1,10 @@ +# 属性测试 + +测试配置 `attributes` 后的行为。本模块测试采用分类的方式,分散到四个测试文件。 + +## 属性的作用 + +利用属性可定制模型的行为,包括: + +- 定制 API 调用,如 `list`, `find` 等; +- 添加自定义函数或属性,如 `getFullName` 等。 diff --git a/test/attributesConfig/dynamic.object.test.js b/test/attributesConfig/dynamic.object.test.js new file mode 100644 index 0000000..8809167 --- /dev/null +++ b/test/attributesConfig/dynamic.object.test.js @@ -0,0 +1,54 @@ +/* config: + * - defineAttributesIn: 'object' + * - dynamicAttributes: true + * + */ +const test = require('ava') +const Model = require('../../lib/model') + +// 定义 Model 类 +const User = Model.extend({ + attributes: { + name: {}, + age: {} + }, + config: { + defineAttributesIn: 'object', + dynamicAttributes: true + } +}) + +test('set attributes through constructor', t => { + const user = new User({ name: 'Jim', foo: 'foo' }) + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.is(user.foo, 'foo') + + t.deepEqual(Object.keys(user), ['name', 'age', 'foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), []) +}) + +test('set attributes through `attributes` property', t => { + const user = new User({ age: 18, bar: 'bar' }) + user.attributes = { name: 'Jim', foo: 'foo' } + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.is(user.foo, 'foo') + t.false('bar' in user) + + t.deepEqual(Object.keys(user), ['name', 'age', 'foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), []) +}) + +test('set attributes through dot operator', t => { + const user = new User({ age: 18 }) + user.name = 'Jim' + user.foo = 'foo' + + t.deepEqual(user.attributes, { name: 'Jim', age: 18, foo: 'foo' }) + + t.deepEqual(Object.keys(user), ['name', 'age', 'foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), []) +}) diff --git a/test/attributesConfig/dynamic.prototype.test.js b/test/attributesConfig/dynamic.prototype.test.js new file mode 100644 index 0000000..8bbac79 --- /dev/null +++ b/test/attributesConfig/dynamic.prototype.test.js @@ -0,0 +1,54 @@ +/* config: + * - defineAttributesIn: 'prototype' + * - dynamicAttributes: true + * + */ +const test = require('ava') +const Model = require('../../lib/model') + +// 定义 Model 类 +const User = Model.extend({ + attributes: { + name: {}, + age: {} + }, + config: { + defineAttributesIn: 'prototype', + dynamicAttributes: true + } +}) + +test('set attributes through constructor', t => { + const user = new User({ name: 'Jim', foo: 'foo' }) + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.is(user.foo, 'foo') + + t.deepEqual(Object.keys(user), ['foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), ['name', 'age']) +}) + +test('set attributes through `attributes` property', t => { + const user = new User({ age: 18, bar: 'bar' }) + user.attributes = { name: 'Jim', foo: 'foo' } + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.is(user.foo, 'foo') + t.false('bar' in user) + + t.deepEqual(Object.keys(user), ['foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), ['name', 'age']) +}) + +test('set attributes through dot operator', t => { + const user = new User({ age: 18 }) + user.name = 'Jim' + user.foo = 'foo' + + t.deepEqual(user.attributes, { name: 'Jim', age: 18, foo: 'foo' }) + + t.deepEqual(Object.keys(user), ['foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), ['name', 'age']) +}) diff --git a/test/attributesConfig/object.test.js b/test/attributesConfig/object.test.js new file mode 100644 index 0000000..5369e91 --- /dev/null +++ b/test/attributesConfig/object.test.js @@ -0,0 +1,51 @@ +/* config: + * - defineAttributesIn: 'object' + * - dynamicAttributes: false + * + */ +const test = require('ava') +const Model = require('../../lib/model') + +const User = Model.extend({ + attributes: { + name: {}, + age: {} + }, + config: { + defineAttributesIn: 'object' + } +}) + +test('set attributes through constructor', t => { + const user = new User({ name: 'Jim', foo: 'foo' }) + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.false('foo' in user) + + t.deepEqual(Object.keys(user), ['name', 'age']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), []) +}) + +test('set attributes through `attributes` property', t => { + const user = new User({ age: 18 }) + user.attributes = { name: 'Jim', foo: 'foo' } + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.false('foo' in user) + + t.deepEqual(Object.keys(user), ['name', 'age']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), []) +}) + +test('set attributes through dot operator', t => { + const user = new User({ age: 18 }) + user.name = 'Jim' + user.foo = 'foo' + + t.deepEqual(user.attributes, { name: 'Jim', age: 18 }) + + t.deepEqual(Object.keys(user), ['name', 'age', 'foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), []) +}) diff --git a/test/attributesConfig/prototype.test.js b/test/attributesConfig/prototype.test.js new file mode 100644 index 0000000..fc35768 --- /dev/null +++ b/test/attributesConfig/prototype.test.js @@ -0,0 +1,51 @@ +/* config: + * - defineAttributesIn: 'prototype' + * - dynamicAttributes: false + * + */ +const test = require('ava') +const Model = require('../../lib/model') + +const User = Model.extend({ + attributes: { + name: {}, + age: {} + }, + config: { + defineAttributesIn: 'prototype' + } +}) + +test('set attributes through constructor', t => { + const user = new User({ name: 'Jim', foo: 'foo' }) + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.false('foo' in user) + + t.deepEqual(Object.keys(user), []) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), ['name', 'age']) +}) + +test('set attributes through `attributes` property', t => { + const user = new User({ age: 18 }) + user.attributes = { name: 'Jim', foo: 'foo' } + + t.is(user.name, 'Jim') + t.is(user.age, null) + t.false('foo' in user) + + t.deepEqual(Object.keys(user), []) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), ['name', 'age']) +}) + +test('set attributes through dot operator', t => { + const user = new User({ age: 18 }) + user.name = 'Jim' + user.foo = 'foo' + + t.deepEqual(user.attributes, { name: 'Jim', age: 18 }) + + t.deepEqual(Object.keys(user), ['foo']) + t.deepEqual(Object.keys(Object.getPrototypeOf(user)), ['name', 'age']) +}) diff --git a/test/attributesDefault.test.js b/test/attributesDefault.test.js new file mode 100644 index 0000000..fe9a9a1 --- /dev/null +++ b/test/attributesDefault.test.js @@ -0,0 +1,24 @@ +const test = require('ava') +const Model = require('../lib/model') + +const User = Model.extend({ + attributes: { + name: { default () { return 'Jim' } }, + age: { default: 18 } + } +}) + +test('default works in constructor', t => { + const user = new User({ name: 'Jam' }) + + t.is(user.name, 'Jam') + t.is(user.age, 18) +}) + +test('default works in set attributes method', t => { + const user = new User({ name: 'Jam' }) + user.attributes = { age: 20 } + + t.is(user.name, 'Jim') + t.is(user.age, 20) +}) diff --git a/test/collection.test.js b/test/collection.test.js new file mode 100644 index 0000000..0686d8a --- /dev/null +++ b/test/collection.test.js @@ -0,0 +1,73 @@ +const test = require('ava') +const Model = require('../lib/model') +const Collection = require('../lib/collection') + +const User = Model.extend({ + attributes: { name: {}, age: {} } +}) + +test('集合是一个简易数组', t => { + const Users = Collection.extend({ + model: User + }) + + const users = new Users() + users.push(new User({ name: 'Jim', age: 18 })) + users.push(new User({ name: 'James', age: 19 })) + users.push(new User({ name: 'Jane', age: 20 })) + + t.is(users.length, 3) + t.deepEqual(users[0].attributes, { name: 'Jim', age: 18 }) + t.deepEqual(users[1].attributes, { name: 'James', age: 19 }) + t.deepEqual(users[2].attributes, { name: 'Jane', age: 20 }) +}) + +test('集合拥有与数组一致的方法', t => { + const Users = Collection.extend({ + model: User + }) + + const users = new Users() + users.push(new User({ name: 'Jim', age: 18 })) + users.push(new User({ name: 'James', age: 19 })) + users.push(new User({ name: 'Jane', age: 20 })) + + users.shift() // 拿 shift 方法举例 + t.is(users.length, 2) +}) + +test('自定义 onTransform', t => { + const Users = Collection.extend({ + model: User, + onTransform (downstreamRecord) { + this.newRecord = downstreamRecord + } + }) + + const users = new Users() + const user = users.new() + user.attributes = { name: 'Jane', age: 20 } + + user.transform() + t.deepEqual(users.newRecord.attributes, { name: 'Jane', age: 20 }) +}) + +test('集合默认的 transformer 效果', t => { + const User = Model.extend({ + attributes: { id: {}, name: {}, age: {} } + }) + const Users = Collection.extend({ + model: User + }) + + const users = new Users() + users.push(new User({ id: 1, name: 'Jim', age: 18 })) + users.push(new User({ id: 2, name: 'James', age: 19 })) + + const user = users.new() + user.attributes = { id: 3, name: 'Jane', age: 20 } + user.transform() + + t.is(users.length, 3) + t.deepEqual(users[2].attributes, { id: 3, name: 'Jane', age: 20 }) +}) diff --git a/test/computedAttributes.test.js b/test/computedAttributes.test.js new file mode 100644 index 0000000..70defcd --- /dev/null +++ b/test/computedAttributes.test.js @@ -0,0 +1,35 @@ +const test = require('ava') +const Model = require('../lib/model') + +const User = Model.extend({ + attributes: { + firstName: {}, + lastName: {} + }, + computed: { + fullName: { + get () { + return this.firstName + ' ' + this.lastName + }, + set (fullName) { + const [firstName, lastName] = fullName.split(' ') + this.firstName = firstName + this.lastName = lastName + } + } + } +}) + +test('get fullName', t => { + const user = new User({ firstName: 'James', lastName: 'Dean' }) + + t.is(user.fullName, 'James Dean') +}) + +test('define static action in model class', t => { + const user = new User() + user.fullName = 'James Dean' + + t.is(user.firstName, 'James') + t.is(user.lastName, 'Dean') +}) diff --git a/test/methods.test.js b/test/methods.test.js new file mode 100644 index 0000000..ab60e23 --- /dev/null +++ b/test/methods.test.js @@ -0,0 +1,55 @@ +const test = require('ava') +const Model = require('../lib/model') + +const User = Model.extend({ + attributes: { + name: {}, + age: {} + }, + actions: { + foo () { + return this.attributes + }, + asyncFoo () { + return new Promise(resolve => { + setTimeout(() => resolve('foo'), 0) + }) + } + }, + methods: { + bar () { + return 'bar' + } + }, + static: { + bar () { + return this + } + } +}) + +test('define action in prototype', t => { + const user = new User({ name: 'Jim', age: 18 }) + + t.true('foo' in Object.getPrototypeOf(user)) + t.deepEqual(user.foo(), user.attributes) +}) + +test('define async action in prototype', async t => { + const user = new User({ name: 'Jim', age: 18 }) + + t.true('asyncFoo' in Object.getPrototypeOf(user)) + t.deepEqual(await user.asyncFoo(), 'foo') +}) + +test('define method in prototype', t => { + const user = new User({ name: 'Jim', age: 18 }) + + t.true('bar' in Object.getPrototypeOf(user)) + t.deepEqual(user.bar(), 'bar') +}) + +test('define static action in model class', t => { + t.true('bar' in User) + t.is(User.bar(), User) +}) diff --git a/test/mixin.test.js b/test/mixin.test.js new file mode 100644 index 0000000..e49e555 --- /dev/null +++ b/test/mixin.test.js @@ -0,0 +1,101 @@ +const test = require('ava') +const Model = require('../lib/model') + +test('mixin add an attribute definition', t => { + const User = Model.extend({ + attributes: { + name: { type: String } + }, + mixin: [ + { + attributes: { + age: { type: Number } + } + } + ] + }) + + const user = new User({ name: 'Jim', age: 18 }) + t.is(user.name, 'Jim') + t.is(user.age, 18) +}) + +test('mixin ignore an exist attribute definition', t => { + const User = Model.extend({ + attributes: { + name: { type: String } + }, + mixin: [ + { + attributes: { + name: { type: String, default: 18 } + } + } + ] + }) + + const user = new User() + t.is(user.name, null) // default not work +}) + +test('mixin adds an part', t => { + const User = Model.extend({ + attributes: { + name: { type: String } + }, + mixin: [ + { + computed: { + capitalized: { + get () { + return this.name[0].toUpperCase() + this.name.substr(1) + } + } + } + } + ] + }) + + const user = new User({ name: 'jim' }) + t.is(user.capitalized, 'Jim') +}) + +test('mixin ignore unknown part', t => { + t.notThrows(() => { + Model.extend({ + attributes: { + name: { type: String } + }, + mixin: [ + { + unknown: { + foo: 'foo', + bar: 'bar' + } + } + ] + }) + }) +}) + +test('following mixin overloads previous one', t => { + const User = Model.extend({ + mixin: [ + { + attributes: { + name: { type: String}, + age: { type: String } + } + }, + { + attributes: { + age: { type: Number } + } + } + ] + }) + + const user = new User({ name: 'Jim', age: '18' }) + t.is(user.name, 'Jim') // name preserved + t.is(user.age, 18) // type converted +}) diff --git a/test/model.config.test.js b/test/model.config.test.js new file mode 100644 index 0000000..5101e4d --- /dev/null +++ b/test/model.config.test.js @@ -0,0 +1,56 @@ +/* 测试 Model.config 方法 + * + */ + +const test = require('ava') +const Model = require('../lib/model') + +test('Model.defaultConfig', t => { + t.like(Model.defaultConfig, { + dynamicAttributes: false, + defineAttributesIn: 'prototype' + }) +}) + +test('Model.config return a new ModelFactory with different defaultConfig', t => { + const modelFactory = Model.config({ + dynamicAttributes: true + }) + + t.like(modelFactory.defaultConfig, { + dynamicAttributes: true, + defineAttributesIn: 'prototype' + }) +}) + +test('Model.defaultConfig works on new model class', t => { + const modelFactory = Model.config({ + dynamicAttributes: true + }) + const modelClass = modelFactory.extend() + + // dynamicAttributes works + const model = new modelClass({ a: 1, b: 2 }) + t.is(model.a, 1) +}) + +test('Model.extend override Model.config', t => { + const modelFactory = Model.config({ + dynamicAttributes: true, + defineAttributesIn: 'prototype' + }) + const modelClass = modelFactory.extend({ + attributes: { + a: {}, b: {} + }, + config: { + defineAttributesIn: 'object' + } + }) + + const model = new modelClass({ a: 1, b: 2, c: 3 }) + // dynamicAttributes works + t.is(model.c, 3) + // defineAttributesIn: 'object' + t.deepEqual(Object.keys(model), ['a', 'b', 'c']) +}) diff --git a/test/modelName.test.js b/test/modelName.test.js new file mode 100644 index 0000000..3474e22 --- /dev/null +++ b/test/modelName.test.js @@ -0,0 +1,17 @@ +const test = require('ava') +const Model = require('../lib/model') + +const User = Model.extend({ + name: 'User' +}) + +test('get model name', t => { + t.is(User.name, 'User') +}) + +test('get model class', t => { + const user = new User() + + t.is(user.constructor, User) + t.is(user.$model, User) +}) diff --git a/test/setterAndDeleter.test.js b/test/setterAndDeleter.test.js new file mode 100644 index 0000000..0314d6b --- /dev/null +++ b/test/setterAndDeleter.test.js @@ -0,0 +1,31 @@ +const test = require('ava') +const Model = require('../lib/model') + +let setterExecuted = '' +let deleterExecuted = '' + +const User = Model.extend({ + config: { + dynamicAttributes: true, + setter (key, value) { + setterExecuted = key + this[key] = value + }, + deleter (key) { + deleterExecuted = key + delete this[key] + } + } +}) + +test('setter and deleter', t => { + const user = new User({ a: 1 }) + + t.deepEqual(user.attributes, { a: 1 }) + t.is(setterExecuted, 'a') + + user.attributes = { b: 2 } + t.deepEqual(user.attributes, { b: 2 }) + t.is(setterExecuted, 'b') + t.is(deleterExecuted, 'a') +}) diff --git a/test/transform.test.js b/test/transform.test.js new file mode 100644 index 0000000..f7a72c0 --- /dev/null +++ b/test/transform.test.js @@ -0,0 +1,73 @@ +const test = require('ava') +const Model = require('../lib/model') + +test('derive', t => { + const User = Model.extend({ + attributes: { name: {}, age: {} } + }) + + const user = new User({ name: 'Jim', age: 18 }) + const user2 = user.derive() + + t.deepEqual(user2.attributes, { name: 'Jim', age: 18 }) +}) + +test('默认情况下,transform 方法会将属性传递给上游', t => { + const User = Model.extend({ + attributes: { name: {}, age: {} }, + }) + + const user = new User({ name: 'Jim', age: 18 }) + const user2 = user.derive() + user2.attributes = { name: 'James', age: 19 } + + user2.transform() + t.deepEqual(user.attributes, { name: 'James', age: 19 }) +}) + +test('自定义 onTransform', t => { + const User = Model.extend({ + attributes: { name: {}, age: {} }, + onTransform (downstreamRecord) { + this.attributes2 = downstreamRecord.attributes + } + }) + + const user = new User({ name: 'Jim', age: 18 }) + const user2 = user.derive() + user2.attributes = { name: 'James', age: 19 } + + user2.transform() + t.deepEqual(user.attributes, { name: 'Jim', age: 18 }) + t.deepEqual(user.attributes2, { name: 'James', age: 19 }) +}) + +test('action 会默认调用 transform', t => { + const User = Model.extend({ + attributes: { name: {}, age: {} }, + actions: { + save () {} + } + }) + + const user = new User({ name: 'Jim', age: 18 }) + const user2 = user.derive() + + user2.attributes = { name: 'James', age: 19 } + user2.save() + t.deepEqual(user.attributes, { name: 'James', age: 19 }) +}) + +test('调用 transform 方法对没有连接的 record 没有影响', t => { + const User = Model.extend({ + attributes: { name: {}, age: {} }, + onTransform (attributes) { + this.attributes = attributes + } + }) + + const user = new User({ name: 'Jim', age: 18 }) + user.transform() + + t.pass() +}) diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..6634752 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1916 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.14.5" + resolved "https://registry.nlark.com/@babel/code-frame/download/@babel/code-frame-7.14.5.tgz?cache=0&sync_timestamp=1623280394200&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" + integrity sha1-I7CNdA6D9JxeWZRfvxtD6Au/Tts= + dependencies: + "@babel/highlight" "^7.14.5" + +"@babel/helper-validator-identifier@^7.14.5": + version "7.14.9" + resolved "https://registry.nlark.com/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.14.9.tgz?cache=0&sync_timestamp=1627804430461&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" + integrity sha1-ZlTRcbICT22O4VG/JQlpmRkTHUg= + +"@babel/highlight@^7.14.5": + version "7.14.5" + resolved "https://registry.nlark.com/@babel/highlight/download/@babel/highlight-7.14.5.tgz?cache=0&sync_timestamp=1623280393681&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhighlight%2Fdownload%2F%40babel%2Fhighlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha1-aGGlLwOWZAUAH2qlNKAaJNmejNk= + dependencies: + "@babel/helper-validator-identifier" "^7.14.5" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@concordance/react@^2.0.0": + version "2.0.0" + resolved "https://registry.npm.taobao.org/@concordance/react/download/@concordance/react-2.0.0.tgz#aef913f27474c53731f4fd79cc2f54897de90fde" + integrity sha1-rvkT8nR0xTcx9P15zC9UiX3pD94= + dependencies: + arrify "^1.0.1" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.nlark.com/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha1-dhnC6yGyVIP20WdUi0z9WnSIw9U= + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.nlark.com/@nodelib/fs.stat/download/@nodelib/fs.stat-2.0.5.tgz?cache=0&sync_timestamp=1622792655362&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40nodelib%2Ffs.stat%2Fdownload%2F%40nodelib%2Ffs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha1-W9Jir5Tp0lvR5xsF3u1Eh2oiLos= + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.nlark.com/@nodelib/fs.walk/download/@nodelib/fs.walk-1.2.8.tgz?cache=0&sync_timestamp=1625769815389&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40nodelib%2Ffs.walk%2Fdownload%2F%40nodelib%2Ffs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha1-6Vc36LtnRt3t9pxVaVNJTxlv5po= + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.nlark.com/@sindresorhus/is/download/@sindresorhus/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha1-n7OjzzEyMoFR81PeRjLgHlIQK+o= + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.nlark.com/@szmarczak/http-timer/download/@szmarczak/http-timer-1.1.2.tgz?cache=0&sync_timestamp=1629502165113&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40szmarczak%2Fhttp-timer%2Fdownload%2F%40szmarczak%2Fhttp-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha1-sWZeLEYaLNkvTBu/UNVFTeDUtCE= + dependencies: + defer-to-connect "^1.0.1" + +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.nlark.com/@types/normalize-package-data/download/@types/normalize-package-data-2.4.1.tgz?cache=0&sync_timestamp=1629708441689&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fnormalize-package-data%2Fdownload%2F%40types%2Fnormalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha1-0zV0eaD9/dWQf+Z+F+CoXJBuEwE= + +acorn-walk@^8.0.0: + version "8.1.1" + resolved "https://registry.nlark.com/acorn-walk/download/acorn-walk-8.1.1.tgz?cache=0&sync_timestamp=1624951990736&other_urls=https%3A%2F%2Fregistry.nlark.com%2Facorn-walk%2Fdownload%2Facorn-walk-8.1.1.tgz#3ddab7f84e4a7e2313f6c414c5b7dac85f4e3ebc" + integrity sha1-Pdq3+E5KfiMT9sQUxbfayF9OPrw= + +acorn@^8.0.4: + version "8.4.1" + resolved "https://registry.nlark.com/acorn/download/acorn-8.4.1.tgz?cache=0&sync_timestamp=1624526855420&other_urls=https%3A%2F%2Fregistry.nlark.com%2Facorn%2Fdownload%2Facorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c" + integrity sha1-VsNiUfx8q8cJatwY8Fr+gUMhoow= + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.nlark.com/aggregate-error/download/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha1-kmcP9Q9TWb23o+DUDQ7DDFc3aHo= + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/ansi-align/download/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha1-tTazcc9ofKrvI2wY0+If43l0Z8s= + dependencies: + string-width "^3.0.0" + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc= + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.nlark.com/ansi-regex/download/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha1-OIU59VF5vzkznIGvMKZU1p+Hy3U= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.nlark.com/ansi-styles/download/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0= + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha1-7dgDYornHATIWuegkG7a00tkiTc= + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.nlark.com/ansi-styles/download/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha1-B0SWkK1Fd30ZJKwquy/IiV26g2s= + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.nlark.com/anymatch/download/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha1-wFV8CWrzLxBhmPT04qODU343hxY= + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.nlark.com/argparse/download/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE= + dependencies: + sprintf-js "~1.0.2" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.nlark.com/array-find-index/download/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/array-union/download/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha1-t5hCCtvrHego2ErNii4j0+/oXo0= + +arrgv@^1.0.2: + version "1.0.2" + resolved "https://registry.nlark.com/arrgv/download/arrgv-1.0.2.tgz#025ed55a6a433cad9b604f8112fc4292715a6ec0" + integrity sha1-Al7VWmpDPK2bYE+BEvxCknFabsA= + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.nlark.com/arrify/download/arrify-1.0.1.tgz?cache=0&sync_timestamp=1619599497996&other_urls=https%3A%2F%2Fregistry.nlark.com%2Farrify%2Fdownload%2Farrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.nlark.com/arrify/download/arrify-2.0.1.tgz?cache=0&sync_timestamp=1619599497996&other_urls=https%3A%2F%2Fregistry.nlark.com%2Farrify%2Fdownload%2Farrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha1-yWVekzHgq81YjSp8rX6ZVvZnAfo= + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.nlark.com/astral-regex/download/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha1-SDFDxWeu7UeFdZwIZXhtx319LjE= + +ava@^3.15.0: + version "3.15.0" + resolved "https://registry.npm.taobao.org/ava/download/ava-3.15.0.tgz#a239658ab1de8a29a243cc902e6b42e4574de2f0" + integrity sha1-ojllirHeiimiQ8yQLmtC5FdN4vA= + dependencies: + "@concordance/react" "^2.0.0" + acorn "^8.0.4" + acorn-walk "^8.0.0" + ansi-styles "^5.0.0" + arrgv "^1.0.2" + arrify "^2.0.1" + callsites "^3.1.0" + chalk "^4.1.0" + chokidar "^3.4.3" + chunkd "^2.0.1" + ci-info "^2.0.0" + ci-parallel-vars "^1.0.1" + clean-yaml-object "^0.1.0" + cli-cursor "^3.1.0" + cli-truncate "^2.1.0" + code-excerpt "^3.0.0" + common-path-prefix "^3.0.0" + concordance "^5.0.1" + convert-source-map "^1.7.0" + currently-unhandled "^0.4.1" + debug "^4.3.1" + del "^6.0.0" + emittery "^0.8.0" + equal-length "^1.0.0" + figures "^3.2.0" + globby "^11.0.1" + ignore-by-default "^2.0.0" + import-local "^3.0.2" + indent-string "^4.0.0" + is-error "^2.2.2" + is-plain-object "^5.0.0" + is-promise "^4.0.0" + lodash "^4.17.20" + matcher "^3.0.0" + md5-hex "^3.0.1" + mem "^8.0.0" + ms "^2.1.3" + ora "^5.2.0" + p-event "^4.2.0" + p-map "^4.0.0" + picomatch "^2.2.2" + pkg-conf "^3.1.0" + plur "^4.0.0" + pretty-ms "^7.0.1" + read-pkg "^5.2.0" + resolve-cwd "^3.0.0" + slash "^3.0.0" + source-map-support "^0.5.19" + stack-utils "^2.0.3" + strip-ansi "^6.0.0" + supertap "^2.0.0" + temp-dir "^2.0.0" + trim-off-newlines "^1.0.1" + update-notifier "^5.0.1" + write-file-atomic "^3.0.3" + yargs "^16.2.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4= + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.nlark.com/base64-js/download/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha1-GxtEAWClv3rUC2UPCVljSBkDkwo= + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.nlark.com/binary-extensions/download/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0= + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.nlark.com/bl/download/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha1-RRU1JkGCvsL7vIOmKrmM8R2fezo= + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +blueimp-md5@^2.10.0: + version "2.18.0" + resolved "https://registry.npm.taobao.org/blueimp-md5/download/blueimp-md5-2.18.0.tgz#1152be1335f0c6b3911ed9e36db54f3e6ac52935" + integrity sha1-EVK+EzXwxrORHtnjbbVPPmrFKTU= + +boxen@^5.0.0: + version "5.0.1" + resolved "https://registry.nlark.com/boxen/download/boxen-5.0.1.tgz?cache=0&sync_timestamp=1619352184783&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fboxen%2Fdownload%2Fboxen-5.0.1.tgz#657528bdd3f59a772b8279b831f27ec2c744664b" + integrity sha1-ZXUovdP1mncrgnm4MfJ+wsdEZks= + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.0" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.nlark.com/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0= + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.nlark.com/braces/download/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha1-NFThpGLujVmeI23zNs2epPiv4Qc= + dependencies: + fill-range "^7.0.1" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.nlark.com/buffer-from/download/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U= + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.nlark.com/buffer/download/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha1-umLnwTEzBTWCGXFghRqPZI6Z7tA= + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.nlark.com/cacheable-request/download/cacheable-request-6.1.0.tgz?cache=0&sync_timestamp=1623237504263&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcacheable-request%2Fdownload%2Fcacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha1-IP+4vRYrpL4R6VZ9gj22UQUsqRI= + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +callsites@^3.1.0: + version "3.1.0" + resolved "https://registry.nlark.com/callsites/download/callsites-3.1.0.tgz?cache=0&sync_timestamp=1628464722297&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcallsites%2Fdownload%2Fcallsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M= + +camelcase@^6.2.0: + version "6.2.0" + resolved "https://registry.nlark.com/camelcase/download/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha1-kkr4gcnVJaydh/QNlk5c6pgqGAk= + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.nlark.com/chalk/download/chalk-2.4.2.tgz?cache=0&sync_timestamp=1627646697260&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.nlark.com/chalk/download/chalk-4.1.2.tgz?cache=0&sync_timestamp=1627646697260&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha1-qsTit3NKdAhnrrFr8CqtVWoeegE= + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.4.3: + version "3.5.2" + resolved "https://registry.nlark.com/chokidar/download/chokidar-3.5.2.tgz?cache=0&sync_timestamp=1623763535523&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchokidar%2Fdownload%2Fchokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha1-26OXb8rbAW9m/TZQIdkWANAcHnU= + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chunkd@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/chunkd/download/chunkd-2.0.1.tgz#49cd1d7b06992dc4f7fccd962fe2a101ee7da920" + integrity sha1-Sc0dewaZLcT3/M2WL+KhAe59qSA= + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.nlark.com/ci-info/download/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y= + +ci-parallel-vars@^1.0.1: + version "1.0.1" + resolved "https://registry.nlark.com/ci-parallel-vars/download/ci-parallel-vars-1.0.1.tgz#e87ff0625ccf9d286985b29b4ada8485ca9ffbc2" + integrity sha1-6H/wYlzPnShphbKbStqEhcqf+8I= + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.nlark.com/clean-stack/download/clean-stack-2.2.0.tgz?cache=0&sync_timestamp=1621915044030&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fclean-stack%2Fdownload%2Fclean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha1-7oRy27Ep5yezHooQpCfe6d/kAIs= + +clean-yaml-object@^0.1.0: + version "0.1.0" + resolved "https://registry.npm.taobao.org/clean-yaml-object/download/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" + integrity sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g= + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.nlark.com/cli-boxes/download/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha1-3dUDXSUJT84iDpyrQKRYQKRAMY8= + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.nlark.com/cli-cursor/download/cli-cursor-3.1.0.tgz?cache=0&sync_timestamp=1629747481175&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcli-cursor%2Fdownload%2Fcli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha1-JkMFp65JDR0Dvwybp8kl0XU68wc= + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.6.0" + resolved "https://registry.nlark.com/cli-spinners/download/cli-spinners-2.6.0.tgz?cache=0&sync_timestamp=1618847030071&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcli-spinners%2Fdownload%2Fcli-spinners-2.6.0.tgz#36c7dc98fb6a9a76bd6238ec3f77e2425627e939" + integrity sha1-NsfcmPtqmna9YjjsP3fiQlYn6Tk= + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.nlark.com/cli-truncate/download/cli-truncate-2.1.0.tgz?cache=0&sync_timestamp=1628633155345&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fcli-truncate%2Fdownload%2Fcli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha1-w54ovwXtzeW+O5iZKiLe7Vork8c= + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.nlark.com/cliui/download/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha1-oCZe5lVHb8gHrqnfPfjfd4OAi08= + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.nlark.com/clone-response/download/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.nlark.com/clone/download/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +code-excerpt@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/code-excerpt/download/code-excerpt-3.0.0.tgz#fcfb6748c03dba8431c19f5474747fad3f250f10" + integrity sha1-/PtnSMA9uoQxwZ9UdHR/rT8lDxA= + dependencies: + convert-to-spaces "^1.0.1" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg= + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM= + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.nlark.com/color-name/download/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.nlark.com/color-name/download/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha1-wqCah6y95pVD3m9j+jmVyCbFNqI= + +common-path-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/common-path-prefix/download/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" + integrity sha1-fQB6fgfFjEtNX0MxMaGRQbKfEeA= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.nlark.com/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concordance@^5.0.1: + version "5.0.4" + resolved "https://registry.nlark.com/concordance/download/concordance-5.0.4.tgz#9896073261adced72f88d60e4d56f8efc4bbbbd2" + integrity sha1-mJYHMmGtztcviNYOTVb478S7u9I= + dependencies: + date-time "^3.1.0" + esutils "^2.0.3" + fast-diff "^1.2.0" + js-string-escape "^1.0.1" + lodash "^4.17.15" + md5-hex "^3.0.1" + semver "^7.3.2" + well-known-symbols "^2.0.0" + +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.nlark.com/configstore/download/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha1-02UCG130uYzdGH1qOw4/anzF7ZY= + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + +convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.nlark.com/convert-source-map/download/convert-source-map-1.8.0.tgz?cache=0&sync_timestamp=1624045304679&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fconvert-source-map%2Fdownload%2Fconvert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha1-8zc8MtIbTXgN2ABFFGhPt5HKQ2k= + dependencies: + safe-buffer "~5.1.1" + +convert-to-spaces@^1.0.1: + version "1.0.2" + resolved "https://registry.npm.taobao.org/convert-to-spaces/download/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715" + integrity sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU= + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.nlark.com/crypto-random-string/download/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha1-7yp6lm7BEIM4g2m6oC6+rSKbMNU= + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.npm.taobao.org/currently-unhandled/download/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + +date-time@^3.1.0: + version "3.1.0" + resolved "https://registry.nlark.com/date-time/download/date-time-3.1.0.tgz?cache=0&sync_timestamp=1618909496543&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdate-time%2Fdownload%2Fdate-time-3.1.0.tgz#0d1e934d170579f481ed8df1e2b8ff70ee845e1e" + integrity sha1-DR6TTRcFefSB7Y3x4rj/cO6EXh4= + dependencies: + time-zone "^1.0.0" + +debug@^4.3.1: + version "4.3.2" + resolved "https://registry.nlark.com/debug/download/debug-4.3.2.tgz?cache=0&sync_timestamp=1625374675284&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdebug%2Fdownload%2Fdebug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha1-8KScGKyHeeMdSgxgKd+3aHPHQos= + dependencies: + ms "2.1.2" + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.npm.taobao.org/decompress-response/download/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.npm.taobao.org/deep-extend/download/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw= + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.nlark.com/defer-to-connect/download/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha1-MxrgUMCNz3ifjIOnuB8O2U9KxZE= + +del@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/del/download/del-6.0.0.tgz?cache=0&sync_timestamp=1615984345486&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdel%2Fdownload%2Fdel-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" + integrity sha1-C0DQMyzqdD8WFPgYvk/rcXcUyVI= + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npm.taobao.org/dir-glob/download/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha1-Vtv3PZkqSpO6FYT0U0Bj/S5BcX8= + dependencies: + path-type "^4.0.0" + +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.nlark.com/dot-prop/download/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha1-kMzOcIzZzYLMTcjD3dmr3VWyDog= + dependencies: + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.nlark.com/duplexer3/download/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +emittery@^0.8.0: + version "0.8.1" + resolved "https://registry.nlark.com/emittery/download/emittery-0.8.1.tgz?cache=0&sync_timestamp=1622640852431&other_urls=https%3A%2F%2Fregistry.nlark.com%2Femittery%2Fdownload%2Femittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha1-uyPMhtA7MKp1p/c0gZ3uLhunCGA= + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.nlark.com/emoji-regex/download/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.nlark.com/emoji-regex/download/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc= + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.nlark.com/end-of-stream/download/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha1-WuZKX0UFe682JuwU2gyl5LJDHrA= + dependencies: + once "^1.4.0" + +equal-length@^1.0.0: + version "1.0.1" + resolved "https://registry.npm.taobao.org/equal-length/download/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" + integrity sha1-IcoRLUirJLTh5//A5TOdMf38J0w= + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.nlark.com/error-ex/download/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha1-tKxAZIEH/c3PriQvQovqihTU8b8= + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.nlark.com/escalade/download/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA= + +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.npm.taobao.org/escape-goat/download/escape-goat-2.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescape-goat%2Fdownload%2Fescape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha1-Gy3HcANnbEV+x2Cy3GjttkgYhnU= + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.nlark.com/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.nlark.com/escape-string-regexp/download/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha1-owME6Z2qMuI7L9IPUbq9B8/8o0Q= + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/escape-string-regexp/download/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha1-FLqDpdNz49MR5a/KKc9b+tllvzQ= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.nlark.com/esprima/download/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha1-E7BM2z5sXRnfkatph6hpVhmwqnE= + +esutils@^2.0.3: + version "2.0.3" + resolved "https://registry.nlark.com/esutils/download/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q= + +fast-diff@^1.2.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/fast-diff/download/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha1-c+4RmC2Gyq95WYKNUZz+kn+sXwM= + +fast-glob@^3.1.1: + version "3.2.7" + resolved "https://registry.nlark.com/fast-glob/download/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha1-/Wy3otfpqnp4RhEehaGW1rL3ZqE= + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fastq@^1.6.0: + version "1.12.0" + resolved "https://registry.nlark.com/fastq/download/fastq-1.12.0.tgz#ed7b6ab5d62393fb2cc591c853652a5c318bf794" + integrity sha1-7XtqtdYjk/ssxZHIU2UqXDGL95Q= + dependencies: + reusify "^1.0.4" + +figures@^3.2.0: + version "3.2.0" + resolved "https://registry.nlark.com/figures/download/figures-3.2.0.tgz?cache=0&sync_timestamp=1625254307578&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffigures%2Fdownload%2Ffigures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha1-YlwYvSk8YE3EqN2y/r8MiDQXRq8= + dependencies: + escape-string-regexp "^1.0.5" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.nlark.com/fill-range/download/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha1-GRmmp8df44ssfHflGYU12prN2kA= + dependencies: + to-regex-range "^5.0.1" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha1-SRafHXmTQwZG2mHsxa41XCHJe3M= + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.nlark.com/find-up/download/find-up-4.1.0.tgz?cache=0&sync_timestamp=1618846778775&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffind-up%2Fdownload%2Ffind-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk= + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.nlark.com/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.nlark.com/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0= + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha1-T5RBKoLbMvNuOwuXQfipf+sDH34= + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.nlark.com/get-stream/download/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha1-wbJVV189wh1Zv8ec09K0axw6VLU= + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.nlark.com/get-stream/download/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha1-SWaheV7lrOZecGxLe+txJX1uItM= + dependencies: + pump "^3.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.nlark.com/glob-parent/download/glob-parent-5.1.2.tgz?cache=0&sync_timestamp=1626760200164&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ= + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3: + version "7.1.7" + resolved "https://registry.nlark.com/glob/download/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha1-Oxk+kjPwHULQs/eClLvutBj5SpA= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/global-dirs/download/global-dirs-3.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglobal-dirs%2Fdownload%2Fglobal-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" + integrity sha1-cKdv6E6jFas3sfVXbL3n1I73JoY= + dependencies: + ini "2.0.0" + +globby@^11.0.1: + version "11.0.4" + resolved "https://registry.nlark.com/globby/download/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha1-LLr/d8Lypi5x6bKBOme5ejowAaU= + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.nlark.com/got/download/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha1-7fRefWf5lUVwXeH3u+7rEhdl7YU= + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.4: + version "4.2.8" + resolved "https://registry.nlark.com/graceful-fs/download/graceful-fs-4.2.8.tgz?cache=0&sync_timestamp=1628194078324&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha1-5BK40z9eAGWTy9PO5t+fLOu+gCo= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/has-flag/download/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s= + +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.nlark.com/has-yarn/download/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha1-E34RNUp7W/EapctknPDG8/8rLnc= + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.nlark.com/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y= + dependencies: + function-bind "^1.1.1" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha1-3/wL+aIcAiCQkPKqaUKeFBTa8/k= + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.nlark.com/http-cache-semantics/download/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha1-SekcXL82yblLz81xwj1SSex045A= + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.nlark.com/ieee754/download/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha1-jrehCmP/8l0VpXsAFYbRd9Gw01I= + +ignore-by-default@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/ignore-by-default/download/ignore-by-default-2.0.0.tgz#537092018540640459569fe7c8c7a408af581146" + integrity sha1-U3CSAYVAZARZVp/nyMekCK9YEUY= + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.nlark.com/ignore/download/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha1-8VCotQo0KJsz4i9YiavU2AFvDlc= + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.nlark.com/import-lazy/download/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.nlark.com/import-local/download/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha1-qM/QQx0d5KIZlwPQA+PmI2T6bbY= + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.nlark.com/imurmurhash/download/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/indent-string/download/indent-string-4.0.0.tgz?cache=0&sync_timestamp=1618679561483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Findent-string%2Fdownload%2Findent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha1-Yk+PRJfWGbLZdoUx1Y9BIoVNclE= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.nlark.com/inherits/download/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= + +ini@2.0.0: + version "2.0.0" + resolved "https://registry.nlark.com/ini/download/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha1-5f1Vbs3VcmvpePoQAYYurLCpS8U= + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.nlark.com/ini/download/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha1-op2kJbSIBvNHZ6Tvzjlyaa8oQyw= + +irregular-plurals@^3.2.0: + version "3.3.0" + resolved "https://registry.nlark.com/irregular-plurals/download/irregular-plurals-3.3.0.tgz#67d0715d4361a60d9fd9ee80af3881c631a31ee2" + integrity sha1-Z9BxXUNhpg2f2e6ArziBxjGjHuI= + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.nlark.com/is-binary-path/download/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk= + dependencies: + binary-extensions "^2.0.0" + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-ci/download/is-ci-2.0.0.tgz?cache=0&sync_timestamp=1615984407284&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-ci%2Fdownload%2Fis-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw= + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.2.0: + version "2.6.0" + resolved "https://registry.nlark.com/is-core-module/download/is-core-module-2.6.0.tgz?cache=0&sync_timestamp=1629224656971&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-core-module%2Fdownload%2Fis-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" + integrity sha1-11U7JSb+Wbkro+QMjfdX7Ipwnhk= + dependencies: + has "^1.0.3" + +is-error@^2.2.2: + version "2.2.2" + resolved "https://registry.npm.taobao.org/is-error/download/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843" + integrity sha1-wQreGHs8k1EMVHClVngz7iVkmEM= + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.nlark.com/is-extglob/download/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0= + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.nlark.com/is-glob/download/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw= + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.4.0: + version "0.4.0" + resolved "https://registry.npm.taobao.org/is-installed-globally/download/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" + integrity sha1-mg/UB5ScMPhutpWe8beZTtC3tSA= + dependencies: + global-dirs "^3.0.0" + is-path-inside "^3.0.2" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.nlark.com/is-interactive/download/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha1-zqbmrlyHCnsKAAQHC3tYfgJSkS4= + +is-npm@^5.0.0: + version "5.0.0" + resolved "https://registry.nlark.com/is-npm/download/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" + integrity sha1-Q+jWXMVuG2f41HJiz2ZwmRk/Rag= + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.nlark.com/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-2.0.0.tgz?cache=0&sync_timestamp=1618600919478&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-obj%2Fdownload%2Fis-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha1-Rz+wXZc3BeP9liBUUBjKjiLvSYI= + +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.nlark.com/is-path-cwd/download/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s= + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.nlark.com/is-path-inside/download/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha1-0jE2LlOgf/Kw4Op/7QSRYf/RYoM= + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha1-RCf1CrNCnpAl6n1S6QQ6nvQVk0Q= + +is-promise@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/is-promise/download/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" + integrity sha1-Qv+fhCBsGZHSbev1IN1cAQQt0vM= + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.nlark.com/is-unicode-supported/download/is-unicode-supported-0.1.0.tgz?cache=0&sync_timestamp=1625294108348&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-unicode-supported%2Fdownload%2Fis-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha1-PybHaoCVk7Ur+i7LVxDtJ3m1Iqc= + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.nlark.com/is-yarn-global/download/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha1-1QLTOCWQ6jAEiTdGdUyJE5lz4jI= + +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/js-string-escape/download/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz?cache=0&sync_timestamp=1619345098261&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fjs-tokens%2Fdownload%2Fjs-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha1-GSA/tZmR35jjoocFDUZHzerzJJk= + +js-yaml@^3.14.0: + version "3.14.1" + resolved "https://registry.npm.taobao.org/js-yaml/download/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha1-2ugS/bOCX6MGYJqHFzg8UMNqBTc= + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/json-buffer/download/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.nlark.com/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk= + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.nlark.com/json-parse-even-better-errors/download/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha1-fEeAWpQxmSjgV3dAXcEuH3pO4C0= + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/keyv/download/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha1-7MIoSG9pmR5J6UdkhaW+Ho/FxNk= + dependencies: + json-buffer "3.0.0" + +latest-version@^5.1.0: + version "5.1.0" + resolved "https://registry.nlark.com/latest-version/download/latest-version-5.1.0.tgz?cache=0&sync_timestamp=1626951703884&other_urls=https%3A%2F%2Fregistry.nlark.com%2Flatest-version%2Fdownload%2Flatest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha1-EZ3+kI/jjRXfpD7NE/oS7Igy+s4= + dependencies: + package-json "^6.3.0" + +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.nlark.com/lines-and-columns/download/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + +load-json-file@^5.2.0: + version "5.3.0" + resolved "https://registry.nlark.com/load-json-file/download/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3" + integrity sha1-TTweAfocA+p4pgrHr5MsnOU0A/M= + dependencies: + graceful-fs "^4.1.15" + parse-json "^4.0.0" + pify "^4.0.1" + strip-bom "^3.0.0" + type-fest "^0.3.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/locate-path/download/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4= + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.nlark.com/locate-path/download/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha1-Gvujlq/WdqbUJQTQpno6frn2KqA= + dependencies: + p-locate "^4.1.0" + +lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.nlark.com/lodash/download/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw= + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.nlark.com/log-symbols/download/log-symbols-4.1.0.tgz?cache=0&sync_timestamp=1618847128438&other_urls=https%3A%2F%2Fregistry.nlark.com%2Flog-symbols%2Fdownload%2Flog-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha1-P727lbRoOsn8eFER55LlWNSr1QM= + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/lowercase-keys/download/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha1-b54wtHCE2XGnyCD/FabFFnt0wm8= + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/lowercase-keys/download/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha1-JgPni3tLAAbLyi+8yKMgJVislHk= + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.nlark.com/lru-cache/download/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ= + dependencies: + yallist "^4.0.0" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha1-QV6WcEazp/HRhSd9hKpYIDcmoT8= + dependencies: + semver "^6.0.0" + +map-age-cleaner@^0.1.3: + version "0.1.3" + resolved "https://registry.nlark.com/map-age-cleaner/download/map-age-cleaner-0.1.3.tgz?cache=0&sync_timestamp=1629750856019&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmap-age-cleaner%2Fdownload%2Fmap-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo= + dependencies: + p-defer "^1.0.0" + +matcher@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/matcher/download/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" + integrity sha1-vZBg9MW3CqgEHMxvgDaHYJlPMMo= + dependencies: + escape-string-regexp "^4.0.0" + +md5-hex@^3.0.1: + version "3.0.1" + resolved "https://registry.nlark.com/md5-hex/download/md5-hex-3.0.1.tgz?cache=0&sync_timestamp=1620037653352&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmd5-hex%2Fdownload%2Fmd5-hex-3.0.1.tgz#be3741b510591434b2784d79e556eefc2c9a8e5c" + integrity sha1-vjdBtRBZFDSyeE155Vbu/Cyajlw= + dependencies: + blueimp-md5 "^2.10.0" + +mem@^8.0.0: + version "8.1.1" + resolved "https://registry.nlark.com/mem/download/mem-8.1.1.tgz?cache=0&sync_timestamp=1626534487701&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmem%2Fdownload%2Fmem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" + integrity sha1-zxGLNXxlq3t+CBe98AyAYil8ASI= + dependencies: + map-age-cleaner "^0.1.3" + mimic-fn "^3.1.0" + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.npm.taobao.org/merge2/download/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4= + +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.nlark.com/micromatch/download/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha1-iW1Rnf6dsl/OlM63pQCRm/iB6/k= + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs= + +mimic-fn@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" + integrity sha1-ZXVRRbvz42lUuUnBZFBCdFHVynQ= + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.nlark.com/mimic-response/download/mimic-response-1.0.1.tgz?cache=0&sync_timestamp=1628692524926&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmimic-response%2Fdownload%2Fmimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha1-SSNTiHju9CBjy4o+OweYeBSHqxs= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0: + version "1.2.5" + resolved "https://registry.nlark.com/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1618847017774&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI= + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.nlark.com/ms/download/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk= + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.nlark.com/ms/download/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha1-V0yBOM4dK1hh8LRFedut1gxmFbI= + +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.nlark.com/normalize-package-data/download/normalize-package-data-2.5.0.tgz?cache=0&sync_timestamp=1629301872905&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnormalize-package-data%2Fdownload%2Fnormalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg= + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU= + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.nlark.com/normalize-url/download/normalize-url-4.5.1.tgz?cache=0&sync_timestamp=1628689122508&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnormalize-url%2Fdownload%2Fnormalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha1-DdkM8SiO4dExO4cIHJpZMu5IUYo= + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.nlark.com/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.npm.taobao.org/onetime/download/onetime-5.1.2.tgz?cache=0&sync_timestamp=1617889724435&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fonetime%2Fdownload%2Fonetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4= + dependencies: + mimic-fn "^2.1.0" + +ora@^5.2.0: + version "5.4.1" + resolved "https://registry.nlark.com/ora/download/ora-5.4.1.tgz?cache=0&sync_timestamp=1629755504079&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fora%2Fdownload%2Fora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha1-GyZ4Qmr0rEpQkAjl5KyemVnbnhg= + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.nlark.com/p-cancelable/download/p-cancelable-1.1.0.tgz?cache=0&sync_timestamp=1622467988667&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fp-cancelable%2Fdownload%2Fp-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha1-0HjRWjr0CSIMiG8dmgyi5EGrJsw= + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/p-defer/download/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-event@^4.2.0: + version "4.2.0" + resolved "https://registry.npm.taobao.org/p-event/download/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" + integrity sha1-r0sEnIrNka6BCD69Hm9criBEwbU= + dependencies: + p-timeout "^3.1.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-finally%2Fdownload%2Fp-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.nlark.com/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1628812721654&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE= + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/p-locate/download/p-locate-3.0.0.tgz?cache=0&sync_timestamp=1629892761309&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fp-locate%2Fdownload%2Fp-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ= + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.nlark.com/p-locate/download/p-locate-4.1.0.tgz?cache=0&sync_timestamp=1629892761309&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fp-locate%2Fdownload%2Fp-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha1-o0KLtwiLOmApL2aRkni3wpetTwc= + dependencies: + p-limit "^2.2.0" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/p-map/download/p-map-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fp-map%2Fdownload%2Fp-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha1-uy+Vpe2i7BaOySdOBqdHw+KQTSs= + dependencies: + aggregate-error "^3.0.0" + +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.nlark.com/p-timeout/download/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha1-x+F6vJcdKnli74NiazXWNazyPf4= + dependencies: + p-finally "^1.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha1-yyhoVA4xPWHeWPr741zpAE1VQOY= + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.nlark.com/package-json/download/package-json-6.5.0.tgz?cache=0&sync_timestamp=1624549851966&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpackage-json%2Fdownload%2Fpackage-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha1-b+7ayjXnVyWHbQsOZJdGl/7RRbA= + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/parse-json/download/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.nlark.com/parse-json/download/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha1-x2/Gbe5UIxyWKyK8yKcs8vmXU80= + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-ms@^2.1.0: + version "2.1.0" + resolved "https://registry.nlark.com/parse-ms/download/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" + integrity sha1-NIVlp1PUOR+lJAKZVrFyy3dTCX0= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/path-exists/download/path-exists-3.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpath-exists%2Fdownload%2Fpath-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/path-exists/download/path-exists-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpath-exists%2Fdownload%2Fpath-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha1-UTvb4tO5XXdi6METfvoZXGxhtbM= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.nlark.com/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.nlark.com/path-parse/download/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha1-+8EUtgykKzDZ2vWFjkvWi77bZzU= + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/path-type/download/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha1-hO0BwKe6OAr+CdkKjBgNzZ0DBDs= + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: + version "2.3.0" + resolved "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz?cache=0&sync_timestamp=1621648246651&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpicomatch%2Fdownload%2Fpicomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha1-8fBh3o9qS/AiiS4tEoI0+5gwKXI= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE= + +pkg-conf@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/pkg-conf/download/pkg-conf-3.1.0.tgz#d9f9c75ea1bae0e77938cde045b276dac7cc69ae" + integrity sha1-2fnHXqG64Od5OM3gRbJ22sfMaa4= + dependencies: + find-up "^3.0.0" + load-json-file "^5.2.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha1-8JkTPfft5CLoHR2ESCcO6z5CYfM= + dependencies: + find-up "^4.0.0" + +plur@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/plur/download/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" + integrity sha1-cprtsI9FJkX+jFjvEVvxawpz74Q= + dependencies: + irregular-plurals "^3.2.0" + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.nlark.com/prepend-http/download/prepend-http-2.0.0.tgz?cache=0&sync_timestamp=1628547439455&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fprepend-http%2Fdownload%2Fprepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +pretty-ms@^7.0.1: + version "7.0.1" + resolved "https://registry.npm.taobao.org/pretty-ms/download/pretty-ms-7.0.1.tgz#7d903eaab281f7d8e03c66f867e239dc32fb73e8" + integrity sha1-fZA+qrKB99jgPGb4Z+I53DL7c+g= + dependencies: + parse-ms "^2.1.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ= + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pupa@^2.1.1: + version "2.1.1" + resolved "https://registry.nlark.com/pupa/download/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha1-9ej9SvwsXZeCj6pSNUnth0SiDWI= + dependencies: + escape-goat "^2.0.0" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.nlark.com/queue-microtask/download/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha1-SSkii7xyTfrEPg77BYyve2z7YkM= + +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.npm.taobao.org/rc/download/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0= + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.nlark.com/read-pkg/download/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w= + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.nlark.com/readable-stream/download/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha1-M3u9o63AcGvT4CRCaihtS0sskZg= + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.nlark.com/readdirp/download/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha1-dKNwvYVxFuJFspzJc0DNQxoCpsc= + dependencies: + picomatch "^2.2.1" + +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.npm.taobao.org/registry-auth-token/download/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha1-bXtABkQZGJcszV/tzUHcMix5slA= + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.npm.taobao.org/registry-url/download/registry-url-5.1.0.tgz?cache=0&sync_timestamp=1618682318998&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregistry-url%2Fdownload%2Fregistry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha1-6YM0tQ1UNLgRNrROxjjZwgCcUAk= + dependencies: + rc "^1.2.8" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.nlark.com/require-directory/download/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/resolve-cwd/download/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha1-DwB18bslRHZs9zumpuKt/ryxPy0= + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.nlark.com/resolve-from/download/resolve-from-5.0.0.tgz?cache=0&sync_timestamp=1622605305717&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fresolve-from%2Fdownload%2Fresolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha1-w1IlhD3493bfIcV1V7wIfp39/Gk= + +resolve@^1.10.0: + version "1.20.0" + resolved "https://registry.nlark.com/resolve/download/resolve-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.nlark.com/responselike/download/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.nlark.com/restore-cursor/download/restore-cursor-3.1.0.tgz?cache=0&sync_timestamp=1629746923086&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frestore-cursor%2Fdownload%2Frestore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha1-OfZ8VLOnpYzqUjbZXPADQjljH34= + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.nlark.com/reusify/download/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY= + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npm.taobao.org/rimraf/download/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha1-8aVAK6YiCtUswSgrrBrjqkn9Bho= + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npm.taobao.org/run-parallel/download/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha1-ZtE2jae9+SHrnZW9GpIp5/IaQ+4= + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha1-mR7GnSluAxN0fVm9/St0XDX4go0= + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY= + +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.nlark.com/semver-diff/download/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha1-Bfd85Z8yXgDicGr9Z7tQbdscoys= + dependencies: + semver "^6.3.0" + +"semver@2 || 3 || 4 || 5": + version "5.7.1" + resolved "https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc= + +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.nlark.com/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0= + +semver@^7.3.2, semver@^7.3.4: + version "7.3.5" + resolved "https://registry.nlark.com/semver/download/semver-7.3.5.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha1-C2Ich5NI2JmOSw5L6Us/EuYBjvc= + dependencies: + lru-cache "^6.0.0" + +serialize-error@^7.0.1: + version "7.0.1" + resolved "https://registry.nlark.com/serialize-error/download/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" + integrity sha1-8TYLBEf2H/tIPsQVfHN/q313jhg= + dependencies: + type-fest "^0.13.1" + +signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw= + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/slash/download/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ= + +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/slice-ansi/download/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha1-Md3BCTCht+C2ewjJbC9Jt3p4l4c= + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +source-map-support@^0.5.19: + version "0.5.19" + resolved "https://registry.nlark.com/source-map-support/download/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha1-qYti+G3K9PZzmWSMCFKRq56P7WE= + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.nlark.com/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM= + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha1-3s6BrJweZxPl99G28X1Gj6U9iak= + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.nlark.com/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0= + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.nlark.com/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha1-z3D1BILu/cmOPOCmgz5KU87rpnk= + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.10" + resolved "https://registry.nlark.com/spdx-license-ids/download/spdx-license-ids-3.0.10.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fspdx-license-ids%2Fdownload%2Fspdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" + integrity sha1-DZvszN5wA9bGWNSH3UijLwvzAUs= + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.nlark.com/sprintf-js/download/sprintf-js-1.0.3.tgz?cache=0&sync_timestamp=1618847174560&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsprintf-js%2Fdownload%2Fsprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +stack-utils@^2.0.3: + version "2.0.3" + resolved "https://registry.nlark.com/stack-utils/download/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" + integrity sha1-zV8DASb/EWt4zLPAJ/4wJxO2Enc= + dependencies: + escape-string-regexp "^2.0.0" + +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.nlark.com/string-width/download/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha1-InZ74htirxCBV0MG9prFG2IgOWE= + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.nlark.com/string-width/download/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha1-2v1PlVmnWFz7pSnGoKT3NIjr1MU= + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.nlark.com/string_decoder/download/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha1-QvEUWUpGzxqOMLCoT1bHjD7awh4= + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.nlark.com/strip-ansi/download/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4= + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.nlark.com/strip-ansi/download/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha1-CxVx3XZpzNTz4G4U7x7tJiJa5TI= + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/strip-bom/download/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.nlark.com/strip-json-comments/download/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supertap@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/supertap/download/supertap-2.0.0.tgz#8b587d6e14b8e885fa5183a9c45abf429feb9f7f" + integrity sha1-i1h9bhS46IX6UYOpxFq/Qp/rn38= + dependencies: + arrify "^2.0.1" + indent-string "^4.0.0" + js-yaml "^3.14.0" + serialize-error "^7.0.1" + strip-ansi "^6.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.nlark.com/supports-color/download/supports-color-5.5.0.tgz?cache=0&sync_timestamp=1626703342506&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha1-4uaaRKyHcveKHsCzW2id9lMO/I8= + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.nlark.com/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1626703342506&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha1-G33NyzK4E4gBs+R4umpRyqiWSNo= + dependencies: + has-flag "^4.0.0" + +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.nlark.com/temp-dir/download/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha1-vekrBb3+sVFugEycAK1FF38xMh4= + +time-zone@^1.0.0: + version "1.0.0" + resolved "https://registry.nlark.com/time-zone/download/time-zone-1.0.0.tgz?cache=0&sync_timestamp=1618907753793&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftime-zone%2Fdownload%2Ftime-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" + integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0= + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.nlark.com/to-readable-stream/download/to-readable-stream-1.0.0.tgz?cache=0&sync_timestamp=1619072442497&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fto-readable-stream%2Fdownload%2Fto-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha1-zgqgwvPfat+FLvtASng+d8BHV3E= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.nlark.com/to-regex-range/download/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ= + dependencies: + is-number "^7.0.0" + +trim-off-newlines@^1.0.1: + version "1.0.1" + resolved "https://registry.nlark.com/trim-off-newlines/download/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" + integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= + +type-fest@^0.13.1: + version "0.13.1" + resolved "https://registry.nlark.com/type-fest/download/type-fest-0.13.1.tgz?cache=0&sync_timestamp=1629724582306&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" + integrity sha1-AXLLW86AsL1ULqNI21DH4hg02TQ= + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.nlark.com/type-fest/download/type-fest-0.20.2.tgz?cache=0&sync_timestamp=1629724582306&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha1-G/IH9LKPkVg2ZstfvTJ4hzAc1fQ= + +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.nlark.com/type-fest/download/type-fest-0.3.1.tgz?cache=0&sync_timestamp=1629724582306&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha1-Y9ANIE4FlHT+Xht8ARESu9HcKeE= + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.nlark.com/type-fest/download/type-fest-0.6.0.tgz?cache=0&sync_timestamp=1629724582306&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftype-fest%2Fdownload%2Ftype-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha1-jSojcNPfiG61yQraHFv2GIrPg4s= + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.nlark.com/typedarray-to-buffer/download/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha1-qX7nqf9CaRufeD/xvFES/j/KkIA= + dependencies: + is-typedarray "^1.0.0" + +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/unique-string/download/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha1-OcZFH4GvsnSd4rIz4/fF6IQ72J0= + dependencies: + crypto-random-string "^2.0.0" + +update-notifier@^5.0.1: + version "5.1.0" + resolved "https://registry.nlark.com/update-notifier/download/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" + integrity sha1-SrDXx/NqIx3XMWz3cpMT8CFNmtk= + dependencies: + boxen "^5.0.0" + chalk "^4.1.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.4.0" + is-npm "^5.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.1.0" + pupa "^2.1.1" + semver "^7.3.4" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.nlark.com/url-parse-lax/download/url-parse-lax-3.0.0.tgz?cache=0&sync_timestamp=1628547550655&other_urls=https%3A%2F%2Fregistry.nlark.com%2Furl-parse-lax%2Fdownload%2Furl-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.nlark.com/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.nlark.com/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha1-/JH2uce6FchX9MssXe/uw51PQQo= + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.nlark.com/wcwidth/download/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +well-known-symbols@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/well-known-symbols/download/well-known-symbols-2.0.0.tgz#e9c7c07dbd132b7b84212c8174391ec1f9871ba5" + integrity sha1-6cfAfb0TK3uEISyBdDkewfmHG6U= + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.nlark.com/widest-line/download/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha1-gpIzO79my0X/DeFgOxNreuFJbso= + dependencies: + string-width "^4.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM= + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: + version "3.0.3" + resolved "https://registry.nlark.com/write-file-atomic/download/write-file-atomic-3.0.3.tgz?cache=0&sync_timestamp=1618847057132&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrite-file-atomic%2Fdownload%2Fwrite-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha1-Vr1cWlxwSBzRnFcb05q5ZaXeVug= + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/xdg-basedir/download/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha1-S8jZmEQDaWIl74OhVzy7y0552xM= + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.nlark.com/y18n/download/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha1-f0k00PfKjFb5UxSTndzS3ZHOHVU= + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.nlark.com/yallist/download/yallist-4.0.0.tgz?cache=0&sync_timestamp=1622604530774&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fyallist%2Fdownload%2Fyallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI= + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.nlark.com/yargs-parser/download/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha1-LrfcOwKJcY/ClfNidThFxBoMlO4= + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.nlark.com/yargs/download/yargs-16.2.0.tgz?cache=0&sync_timestamp=1628889096518&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fyargs%2Fdownload%2Fyargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha1-HIK/D2tqZur85+8w43b0mhJHf2Y= + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2"