├── .eslintrc.yml ├── .gitignore ├── README.md ├── docs └── rules │ ├── no-root-store-assets.md │ ├── no-root-store-calls.md │ └── require-jsdoc.md ├── lib ├── index.js ├── rules │ ├── no-root-store-assets.js │ ├── no-root-store-calls.js │ └── require-jsdoc.js └── utils.js ├── license ├── package.json ├── tests ├── lib │ └── rules │ │ ├── no-root-store-assets.js │ │ ├── no-root-store-calls.js │ │ └── require-jsdoc.js └── utils.js └── yarn.lock /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: 2 | - airbnb-base 3 | - prettier 4 | parser: babel-eslint 5 | root: true 6 | plugins: 7 | - import 8 | - prettier 9 | rules: 10 | quotes: 11 | - error 12 | - "double" 13 | semi: 14 | - error 15 | - "never" 16 | prettier/prettier: 17 | - error 18 | - semi: false 19 | trailingComma: all 20 | # Let Prettier take care of the following rules 21 | comma-dangle: 0 22 | arrow-parens: 0 23 | object-curly-newline: 0 24 | object-curly-spacing: 0 25 | # Strict mode enabled by eslint-generator 26 | strict: 0 27 | 28 | 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .npmrc 3 | .cache/ 4 | yarn-error.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eslint-plugin-strict-vue 2 | 3 | 4 | [![NPM version](https://img.shields.io/npm/v/eslint-plugin-strict-vue.svg?style=flat)](https://npmjs.org/package/eslint-plugin-strict-vue) 5 | 6 | Various ESLint rules to make you Vue(x) code a bit stricter 7 | 8 | ## 🥋 Requirements 9 | * ESLint >=4.15.0 10 | * Node.js >=8.0.0 11 | 12 | ## 🏋 Installation 13 | ``` 14 | $ npm i eslint eslint-plugin-strict-vue --save-dev 15 | ``` 16 | 17 | ## 🤹‍ Usage 18 | 19 | Configure it in `.eslintrc` or `package.json`: 20 | 21 | ```json 22 | { 23 | "name": "my-awesome-project", 24 | "eslintConfig": { 25 | "parserOptions": { 26 | "ecmaVersion": 2018, 27 | "sourceType": "module" 28 | }, 29 | "plugins": [ 30 | "strict-vue" 31 | ], 32 | "rules": { 33 | "strict-vue/require-jsdoc": "error", 34 | "strict-vue/no-root-store-calls": "error", 35 | "strict-vue/no-root-store-assets": "error", 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | 42 | ## 🎭 Rules 43 | 44 | * [require-jsdoc](./docs/rules/require-jsdoc.md) - require JSdoc comments for Vue props, and Vuex actions and state. 45 | * [no-root-store-calls](./docs/rules/no-root-store-calls.md) - disallow dispatch/commit to the global namespase. 46 | * [no-root-store-assets](./docs/rules/no-root-store-assets.md) - disallow the use of rootGetters and rootStore. 47 | 48 | ## License 49 | MIT 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/rules/no-root-store-assets.md: -------------------------------------------------------------------------------- 1 | # Disallow rootGetters and rootState (no-root-store-assets) 2 | Using rootGetters and rootStore might be harmful in a complex applications. 3 | The rule disallows the use of rootGetters and rootStore. 4 | 5 | ## Rule Details 6 | The use of rootStore and rootGetters binds vuex module to a specific implementation of the root store. In order to reuse module elsewhere we have to re-create a specific set of root getters and a specific root state. 7 | Disallowing root store assets leads to better modules isolation and more explicit dependencies in the code. 8 | 9 | ### How to replace getters using rootState/rootGetters 10 | Case: button title depends on the user name 11 | 12 | :thumbsdown: Examples of **incorrect** code for this rule 13 | ```js 14 | actions: 15 | // root store 16 | state: { 17 | state: { 18 | userName: 'Glebka' 19 | } 20 | } 21 | ``` 22 | 23 | ```js 24 | // AwesomeModule 25 | getters: { 26 | linkTitle(state, getters, rootState) { 27 | return rootState.userName ? `Hail ${rootState.userName}!` : 'Hi man!' 28 | } 29 | } 30 | ``` 31 | 32 | ```js 33 | // container 34 | computed: { 35 | ...mapGetters('AwesomeModule', ['linkTitle']) 36 | } 37 | ``` 38 | 39 | ```diff 40 | // template 41 | span {{linkTitle}} 42 | ``` 43 | 44 | :thumbsup: Examples of **correct** code for this rule: 45 | 46 | ```js 47 | actions: 48 | // root store 49 | state: { 50 | state: { 51 | userName: 'Glebka' 52 | } 53 | } 54 | ``` 55 | 56 | ```diff 57 | // AwesomeModule 58 | getters: { 59 | linkTitle(state, getters) { 60 | // Instead of using rootState return a function that explicitly depends on userName 61 | - return rootState.userName ? `Hail ${rootState.userName}!` : 'Hi man!' 62 | + return userName => userName ? `Hail ${userName}!` : 'Hi man!' 63 | } 64 | } 65 | ``` 66 | 67 | ```diff 68 | // container 69 | computed: { 70 | ...mapGetters('AwesomeModule', ['linkTitle']), 71 | + ...mapState(['userName']), 72 | } 73 | ``` 74 | 75 | ```diff 76 | // template 77 | - span {{linkTitle} 78 | + span {{linkTitle(userName)}} 79 | ``` 80 | 81 | 82 | ### How to replace actions using rootState/rootGetters 83 | Case: weather forecast module depends on the cityID. 84 | 85 | :thumbsdown: Examples of **incorrect** code for this rule 86 | 87 | ```js 88 | // weather module 89 | actions: { 90 | fetchWeatherForecast({ rootGetters }) { 91 | const forecast = await weatherService.getForecast(rootGetters.cityID) 92 | // ... 93 | } 94 | } 95 | ``` 96 | 97 | ```js 98 | // container 99 | methods: { 100 | ...mapActions('weather', ['fetchWeatherForecast']), 101 | mounted() { 102 | this.fetchWeatherForecast(); 103 | } 104 | } 105 | ``` 106 | 107 | :thumbsup: Examples of **correct** code for this rule: 108 | 109 | ```js 110 | // weather module 111 | actions: { 112 | // instead of using rootGetters explicitly pass cityID into the function 113 | fetchWeatherForecast(context, cityID) { 114 | const forecast = await weatherService.getForecast(cityID) 115 | // ... 116 | } 117 | } 118 | ``` 119 | 120 | ```diff 121 | // container 122 | methods: { 123 | ...mapActions('weather', ['fetchWeatherForecast']), 124 | + ...mapGetters(['cityID']), 125 | mounted() { 126 | - this.fetchWeatherForecast(); 127 | + this.fetchWeatherForecast(cityID); 128 | } 129 | } 130 | ``` 131 | 132 | ## When Not To Use It 133 | You might not need this rule if your vuex store is small. 134 | 135 | ## Further Reading 136 | 137 | - [no-root-store-calls](./no-root-store-calls.md) - disallowing dispatch/commit to the global namespase serves the same purposes -------------------------------------------------------------------------------- /docs/rules/no-root-store-calls.md: -------------------------------------------------------------------------------- 1 | # Disallow global commits and global dispatchs (no-root-store-calls) 2 | Using commit or dispatch with the `{ root: true }` option might be harmful in a complex applications. 3 | The rule disallow root store calls like this: 4 | ```js 5 | actions: { 6 | myAction({ commit, dispath }) { 7 | commit('mutation', args, { root: true }) 8 | dispatch({ type: 'anotherAction' }, { root: true }) 9 | } 10 | } 11 | ``` 12 | 13 | ## Rule Details 14 | Root store calls binds vuex module to a specific implementation of the root store. In order to reuse module elsewhere we have to re-create a specific set of root actions, mutations and a specific root state. 15 | Disallowing root store calls leads to better modules isolation and more explicit dependencies in the code. 16 | 17 | :thumbsdown: Examples of **incorrect** code for this rule 18 | 19 | ```js 20 | // user module 21 | login(ctx) { 22 | // ... logining 23 | // After a successful login we need to show welcome popup which is controlled by another module 24 | ctx.dispatch('welcomePopup/show', null, { root: true}) 25 | } 26 | ``` 27 | 28 | ```js 29 | // container 30 | methods: { 31 | ...mapActions('user', ['login']), 32 | handleClick() { 33 | // action call 34 | this.login(); 35 | } 36 | } 37 | ``` 38 | 39 | :thumbsup: Examples of **correct** code for this rule: 40 | 41 | ```diff 42 | // user module 43 | login(ctx) { 44 | // ... logining 45 | - ctx.dispatch('welcomePopup/show', null, { root: true}) 46 | } 47 | ``` 48 | 49 | ```diff 50 | // container 51 | methods: { 52 | ...mapActions('user', ['login']), 53 | ...mapActions('welcomePopup', ['show']), 54 | handleClick() { 55 | await this.login(); 56 | + // instead of dispatching to welocmePopup from login action, call it explicitly in the container: 57 | + this.show() 58 | } 59 | } 60 | ``` 61 | 62 | In some complex cases, you may need to watch state or getters and apply actions based on changed values. 63 | 64 | ## When Not To Use It 65 | You might not need this rule if your vuex store is small. 66 | 67 | ## Further Reading 68 | 69 | - [no-root-store-assets](./no-root-store-assets.md) - disallowing rootState and rootGetters serves the same purposes -------------------------------------------------------------------------------- /docs/rules/require-jsdoc.md: -------------------------------------------------------------------------------- 1 | # Require JSdoc comments (require-jsdoc) 2 | Props is a public api of the Vue component so it should be well documented. The same applies to Vuex state and actions. 3 | 4 | In terms of this rule JSdoc - it's any not empty comment block which starts with `*`. The simplest JSdoc is: 5 | ```js 6 | /** I'm a JSdoc */ 7 | ``` 8 | ## Rule details 9 | 10 | This rule requires JSDoc comments for specified nodes. Supported nodes: 11 | 12 | * `"VueProps"` - each prop should has JSdoc 13 | * `"VuexState"` - each action should has JSdoc 14 | * `"VuexActions"` - each state property should has JSdoc 15 | 16 | ## Options 17 | 18 | This rule has a single object option: 19 | 20 | * `"require"` requires JSDoc comments for the specified nodes 21 | 22 | Default option settings are: 23 | 24 | ```json 25 | { 26 | "require-jsdoc": ["error", { 27 | "require": { 28 | "VueProps": true, 29 | "VuexState": false, 30 | "VuexActions": false 31 | } 32 | }] 33 | } 34 | ``` 35 | 36 | ### require 37 | 38 | :thumbsdown: Examples of **incorrect** code for this rule with the `{ "require": { "VueProps": true, "VuexActions": true, "VuexState": true } }` option: 39 | 40 | 41 | ```js 42 | const GREET_EMEMY = 'greet enemy action'; 43 | 44 | function getInitialState() { 45 | return { 46 | message: 'GREETINGS, TRAVELER', 47 | random: Math.random 48 | } 49 | } 50 | 51 | const actions = { 52 | initState() {}, 53 | [GREET_EMEMY]() {} 54 | } 55 | 56 | export default function getStore(di) { 57 | // ... 58 | return { 59 | state: getInitialState, 60 | getters: {}, 61 | actions 62 | } 63 | } 64 | ``` 65 | 66 | ```js 67 | export default { 68 | props: { 69 | title: { 70 | type: String, 71 | default: "Money income" 72 | }, 73 | samples: { 74 | type: Array, 75 | required: true 76 | } 77 | }, 78 | data() { 79 | return {} 80 | }, 81 | // ... 82 | } 83 | ``` 84 | 85 | :thumbsup: Examples of **correct** code for this rule: 86 | 87 | ```js 88 | const GREET_EMEMY = 'greet enemy action'; 89 | 90 | function getInitialState() { 91 | return { 92 | /** Hunter's greet */ 93 | message: 'GREETINGS, TRAVELER', 94 | /** another well documented property */ 95 | random: Math.random 96 | } 97 | } 98 | 99 | const actions = { 100 | /** This action performs only on server side */ 101 | initState() {}, 102 | /** Greets enemy */ 103 | [GREET_EMEMY]() {} 104 | } 105 | 106 | export default function getStore(di) { 107 | // ... 108 | return { 109 | state: getInitialState, 110 | getters: {}, 111 | actions 112 | } 113 | } 114 | ``` 115 | 116 | ```js 117 | export default { 118 | props: { 119 | /** Graph title */ 120 | title: { 121 | type: String, 122 | default: "Money income" 123 | }, 124 | /** 125 | * Graph data 126 | * @type {Array<{date: Date, money: numer}>} 127 | */ 128 | samples: { 129 | type: Array, 130 | required: true 131 | } 132 | }, 133 | data() { 134 | return {} 135 | }, 136 | // ... 137 | } 138 | ``` 139 | 140 | ## When not to use it 141 | 142 | If you do not require JSdoc for your vue props, vuex state or actions 143 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Набор eslint правил для vuex сторов N1.RU 3 | * @author glebkaf 4 | */ 5 | 6 | "use strict" 7 | 8 | //------------------------------------------------------------------------------ 9 | // Requirements 10 | //------------------------------------------------------------------------------ 11 | 12 | const requireIndex = require("requireindex") 13 | 14 | //------------------------------------------------------------------------------ 15 | // Plugin Definition 16 | //------------------------------------------------------------------------------ 17 | 18 | // import all rules in lib/rules 19 | module.exports.rules = requireIndex(`${__dirname}/rules`) 20 | -------------------------------------------------------------------------------- /lib/rules/no-root-store-assets.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const { 4 | filter, 5 | compose, 6 | pathSatisfies, 7 | forEach, 8 | gte, 9 | map, 10 | pathEq, 11 | path, 12 | cond, 13 | T, 14 | __, 15 | always, 16 | } = require("ramda") 17 | const { 18 | isVuexGetters, 19 | getChildProperties, 20 | getIdentifierValue, 21 | } = require("../utils") 22 | 23 | const reportError = ( 24 | assetName = "rootState and rootGetters", 25 | ) => context => node => { 26 | context.report({ 27 | node, 28 | messageId: "avoidRootAssets", 29 | data: { 30 | assetName, 31 | }, 32 | }) 33 | } 34 | 35 | /** 36 | * Check getters for using root assets: rootState or rootGetter, i.e. 37 | * check that arguments length >= 3 38 | */ 39 | const checkGettersForRootAssets = (node, context) => { 40 | try { 41 | const childProps = getChildProperties(node, context) 42 | 43 | const mapPropertyToFunction = cond([ 44 | [pathEq(["value", "type"], "Identifier"), getIdentifierValue(context)], 45 | [T, path(["value"])], 46 | ]) 47 | 48 | compose( 49 | forEach( 50 | cond([ 51 | [ 52 | pathSatisfies(gte(__, 4), ["params", "length"]), 53 | reportError("rootGetters")(context), 54 | ], 55 | [ 56 | pathSatisfies(gte(__, 3), ["params", "length"]), 57 | reportError("rootState")(context), 58 | ], 59 | [T, always()], 60 | ]), 61 | ), 62 | map(mapPropertyToFunction), 63 | )(childProps) 64 | } catch (e) { 65 | console.error(`${e.message} \n at file: ${context.getFilename()}`) 66 | } 67 | } 68 | 69 | module.exports = { 70 | meta: { 71 | docs: { 72 | description: "Prevent from using rootState and rootGetters", 73 | }, 74 | schema: [], 75 | messages: { 76 | avoidRootAssets: "Don't use {{ assetName }}", 77 | }, 78 | }, 79 | 80 | create(context) { 81 | return { 82 | // handle getters 83 | "ObjectExpression > Property": node => { 84 | if (isVuexGetters(node)) { 85 | checkGettersForRootAssets(node, context) 86 | } 87 | }, 88 | // handle actions 89 | "Property[key.name='rootGetters']": reportError("rootGetters")(context), 90 | "Property[key.name='rootState']": reportError("rootState")(context), 91 | "MemberExpression[property.name='rootGetters']": reportError( 92 | "rootGetters", 93 | )(context), 94 | "MemberExpression[property.name='rootState']": reportError("rootState")( 95 | context, 96 | ), 97 | } 98 | }, 99 | } 100 | -------------------------------------------------------------------------------- /lib/rules/no-root-store-calls.js: -------------------------------------------------------------------------------- 1 | const R = require("ramda") 2 | 3 | /** 4 | * Checks whether commit or dispatch in the global namespace i.e. 5 | * check for { root: true } argument. 6 | */ 7 | const checkRootCall = context => node => { 8 | try { 9 | const arg2 = R.path(["arguments", "1"], node) 10 | const arg3 = R.path(["arguments", "2"], node) 11 | 12 | const isRootArg = arg => 13 | R.pathEq(["properties", "0", "key", "name"], "root", arg) && 14 | R.pathEq(["properties", "0", "value", "value"], true, arg) 15 | 16 | const isRootCall = isRootArg(arg2) || isRootArg(arg3) 17 | const actionName = 18 | R.path(["callee", "name"], node) || 19 | R.path(["callee", "property", "name"], node) 20 | 21 | if (isRootCall) { 22 | context.report({ 23 | node, 24 | messageId: "avoidRootCalls", 25 | data: { 26 | actionName, 27 | }, 28 | }) 29 | } 30 | } catch (e) { 31 | console.error(`${e.message} \n at file: ${context.getFilename()}`) 32 | } 33 | } 34 | 35 | module.exports = { 36 | meta: { 37 | docs: { 38 | description: 39 | "Prevent from dispatching actions or commiting mutations in the global namespace", 40 | }, 41 | schema: [], 42 | messages: { 43 | avoidRootCalls: "Don't {{ actionName }} in the global namespace.", 44 | }, 45 | }, 46 | create(context) { 47 | return { 48 | "CallExpression[callee.name='commit']": checkRootCall(context), 49 | "CallExpression[callee.property.name='commit']": checkRootCall(context), 50 | "CallExpression[callee.name='dispatch']": checkRootCall(context), 51 | "CallExpression[callee.property.name='dispatch']": checkRootCall(context), 52 | } 53 | }, 54 | } 55 | -------------------------------------------------------------------------------- /lib/rules/require-jsdoc.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const R = require("ramda") 4 | const { 5 | getChildProperties, 6 | isVuexActions, 7 | isVuexState, 8 | isVueProps, 9 | } = require("../utils") 10 | 11 | const reportError = context => node => { 12 | if (!node.key) { 13 | throw new Error(`Node has no key: ${node}`) 14 | } 15 | 16 | context.report({ 17 | node: node.key, 18 | message: "Missing JSDoc comment.", 19 | }) 20 | } 21 | 22 | /** Checks that given node has no valid doc */ 23 | const hasNoValidDoc = context => node => { 24 | const comments = context.getCommentsBefore(node) || [] 25 | const hasValidDoc = comments 26 | .filter(({ type }) => type === "Block") 27 | .map(({ value = "" }) => value.trim()) 28 | .some(value => value.startsWith("*") && value.length > 1) 29 | return !hasValidDoc 30 | } 31 | 32 | /** Checks that all properties inside given property has valid doc */ 33 | const checkNestedPropertiesForDoc = (node, context) => { 34 | try { 35 | const childProps = getChildProperties(node, context) 36 | 37 | const filterPropsWithJsdoc = R.filter(hasNoValidDoc(context)) 38 | const jsdoclessProps = filterPropsWithJsdoc(childProps) 39 | 40 | jsdoclessProps.forEach(reportError(context)) 41 | } catch (e) { 42 | console.error(`${e.message} \n at file: ${context.getFilename()}`) 43 | } 44 | } 45 | 46 | module.exports = { 47 | meta: { 48 | docs: { 49 | description: 50 | "Require JSdoc comments at Vue props, and Vuex actions and state.", 51 | category: "Stylistic Issues", 52 | }, 53 | schema: [ 54 | { 55 | type: "object", 56 | properties: { 57 | require: { 58 | type: "object", 59 | properties: { 60 | VueProps: { 61 | type: "boolean", 62 | }, 63 | VuexActions: { 64 | type: "boolean", 65 | }, 66 | VuexState: { 67 | type: "boolean", 68 | }, 69 | }, 70 | additionalProperties: false, 71 | }, 72 | }, 73 | additionalProperties: false, 74 | }, 75 | ], 76 | }, 77 | 78 | create(context) { 79 | const defaultOptions = { 80 | VueProps: true, 81 | VuexActions: false, 82 | VuexState: false, 83 | } 84 | 85 | const { VuexActions, VuexState, VueProps } = R.merge( 86 | defaultOptions, 87 | R.path(["options", 0, "require"], context), 88 | ) 89 | 90 | return { 91 | "ObjectExpression > Property": node => { 92 | if (isVuexActions(node) && VuexActions) { 93 | checkNestedPropertiesForDoc(node, context) 94 | } 95 | 96 | if (isVuexState(node) && VuexState) { 97 | checkNestedPropertiesForDoc(node, context) 98 | } 99 | 100 | if (isVueProps(node) && VueProps) { 101 | checkNestedPropertiesForDoc(node, context) 102 | } 103 | }, 104 | } 105 | }, 106 | } 107 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | const R = require("ramda") 2 | 3 | /** Finds variable with given name */ 4 | function findVariable(scope, variableName) { 5 | if (!scope) { 6 | return undefined 7 | } 8 | const { variables, upper } = scope 9 | const variable = variables.find(({ name }) => variableName === name) 10 | 11 | return variable || findVariable(upper, variableName) 12 | } 13 | 14 | /** 15 | * Finds identifier defenition. 16 | * Using to resolve actual value of link. 17 | */ 18 | const getIdentifierDefenition = context => identifier => { 19 | const { name } = identifier.value 20 | const variable = findVariable(context.getScope(identifier.value), name) 21 | 22 | if (!variable) { 23 | throw new Error(`Cant find variable assigned to identifier: '${name}'`) 24 | } 25 | 26 | const defenition = R.last(variable.defs) 27 | 28 | if (!defenition) { 29 | throw new Error(`Cant find defenition of variable: '${variable.name}'`) 30 | } 31 | 32 | return defenition 33 | } 34 | 35 | /** 36 | * Finds identifier value. 37 | * Using to resolve actual value of link. 38 | */ 39 | const getIdentifierValue = context => identifier => { 40 | const { type, node } = getIdentifierDefenition(context)(identifier) 41 | 42 | if (type === "Variable") { 43 | return node.init // => Variable Value 44 | } 45 | 46 | if (type === "FunctionName") { 47 | return node // => FunctionDeclaration 48 | } 49 | 50 | // can't resolve Identifier value 51 | return null 52 | } 53 | 54 | /** 55 | * Find return statement value. 56 | * Using when linting component's data, and vuex's state. 57 | */ 58 | const findReturnStatement = node => { 59 | if (!node.body) { 60 | return undefined 61 | } 62 | 63 | const returnStatement = R.find( 64 | ({ type }) => type === "ReturnStatement", 65 | node.body, 66 | ) 67 | 68 | return returnStatement || findReturnStatement(node.body) 69 | } 70 | 71 | // Skip spread elements for now 72 | const filterUnsupportedProps = properties => 73 | properties 74 | .filter(({ type }) => type !== "SpreadElement") // eslint 5+ 75 | .filter(({ type }) => type !== "ExperimentalSpreadProperty") // eslint 4, babel-eslint 76 | 77 | /** Return child properties of given node */ 78 | const getChildProperties = (node, context) => { 79 | if (node.value.type === "ObjectExpression") { 80 | return filterUnsupportedProps(node.value.properties) 81 | } 82 | 83 | if (node.value.type === "Identifier") { 84 | const value = getIdentifierValue(context)(node) 85 | 86 | if (!value) { 87 | return [] 88 | } 89 | 90 | if (value.type === "FunctionDeclaration") { 91 | const returnStatement = findReturnStatement(value) 92 | return filterUnsupportedProps(returnStatement.argument.properties) 93 | } 94 | 95 | if (value.type === "ObjectExpression") { 96 | return filterUnsupportedProps(value.properties) 97 | } 98 | 99 | return [] 100 | } 101 | 102 | return [] 103 | } 104 | 105 | /** 106 | * Checks that given property is inside vuex store object. 107 | * Assume that we are working with vuex object, if it contain 2 or more valid vuex keys 108 | */ 109 | const isWithinVuexStore = property => { 110 | const validKeys = [ 111 | "state", 112 | "actions", 113 | "mutations", 114 | "getters", 115 | "namespaced", 116 | "modules", 117 | ] 118 | 119 | const keys = property.parent.properties.map(R.path(["key", "name"])) 120 | 121 | const hasOnlyStateAndGetters = R.equals( 122 | keys.sort(), 123 | ["state", "getters"].sort(), 124 | ) 125 | 126 | /** 127 | * Can't decide whether object is vuex store or it is action context 128 | * if it has only state and getters 129 | */ 130 | if (hasOnlyStateAndGetters) { 131 | return false 132 | } 133 | 134 | const vaildKeysInsideProperties = R.innerJoin( 135 | (key, vaildKey) => key === vaildKey, 136 | keys, 137 | validKeys, 138 | ) 139 | const hasOnlyValidKeys = R.all(key => validKeys.includes(key), keys) 140 | 141 | return R.length(vaildKeysInsideProperties) >= 2 && hasOnlyValidKeys 142 | } 143 | 144 | /** 145 | * Checks that given property is inside vue component object. 146 | * Assume that we are working with vue component, if it contain 2 or more valid vue keys 147 | */ 148 | const isWithinVueComponent = property => { 149 | const validKeys = [ 150 | "props", 151 | "data", 152 | "components", 153 | "computed", 154 | "methods", 155 | "watch", 156 | ] 157 | const keys = property.parent.properties.map(R.path(["key", "name"])) 158 | const vaildKeysInsideProperties = R.innerJoin( 159 | (key, vaildKey) => key === vaildKey, 160 | keys, 161 | validKeys, 162 | ) 163 | return R.length(vaildKeysInsideProperties) >= 2 164 | } 165 | 166 | const isVuexActions = node => 167 | isWithinVuexStore(node) && node.key.name === "actions" 168 | 169 | const isVuexGetters = node => 170 | isWithinVuexStore(node) && node.key.name === "getters" 171 | 172 | const isVuexState = node => isWithinVuexStore(node) && node.key.name === "state" 173 | 174 | const isVueProps = node => 175 | isWithinVueComponent(node) && node.key.name === "props" 176 | 177 | module.exports = { 178 | getIdentifierDefenition, 179 | getIdentifierValue, 180 | getChildProperties, 181 | isVuexGetters, 182 | isVuexActions, 183 | isVuexState, 184 | isVueProps, 185 | } 186 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Sindre Sorhus (sindresorhus.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-plugin-strict-vue", 3 | "version": "1.0.0", 4 | "description": "Various ESLint rules to make you Vue(x) code a bit stricter", 5 | "keywords": [ 6 | "eslint", 7 | "eslintplugin", 8 | "vue", 9 | "vuex", 10 | "jsdoc" 11 | ], 12 | "author": "glebkaf", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/GlebkaF/eslint-plugin-strict-vue" 17 | }, 18 | "main": "lib/index.js", 19 | "scripts": { 20 | "test": "mocha tests --recursive" 21 | }, 22 | "dependencies": { 23 | "ramda": "^0.25.0", 24 | "requireindex": "~1.1.0" 25 | }, 26 | "devDependencies": { 27 | "babel-eslint": "^8.2.6", 28 | "eslint": "^5.3.0", 29 | "eslint-config-airbnb-base": "^13.0.0", 30 | "eslint-config-prettier": "^2.9.0", 31 | "eslint-plugin-import": "^2.13.0", 32 | "eslint-plugin-prettier": "^2.6.2", 33 | "mocha": "^3.1.2", 34 | "prettier": "^1.14.0" 35 | }, 36 | "engines": { 37 | "node": ">=8" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/lib/rules/no-root-store-assets.js: -------------------------------------------------------------------------------- 1 | const R = require("ramda") 2 | const { RuleTester } = require("eslint") 3 | const rule = require("../../../lib/rules/no-root-store-assets") 4 | const { prepareCases } = require("../../utils") 5 | 6 | RuleTester.setDefaultConfig({ 7 | parserOptions: { 8 | ecmaVersion: 2018, 9 | sourceType: "module", 10 | }, 11 | }) 12 | 13 | const ruleTester = new RuleTester() 14 | 15 | const invalidCases = [ 16 | { 17 | title: "Root state and getters used by getters", 18 | code: ` 19 | const getter5 = function(state, getters, { a }, { b }) {}; 20 | 21 | const store = { 22 | state: {}, 23 | namespaced: true, 24 | getters: { 25 | getter1(state, getters, rootState, rootGetters) {}, 26 | getter2(state, getters, rS, rG) {}, 27 | getter3(state, getters, { asd }, { qwe }) {}, 28 | getter4: (state, getters, rootState, rootGetters) => {}, 29 | getter5, 30 | }, 31 | }; 32 | `, 33 | errors: R.times( 34 | R.always({ 35 | messageId: "avoidRootAssets", 36 | }), 37 | 5, 38 | ), 39 | }, 40 | { 41 | title: "Deep linked getter", 42 | code: ` 43 | const getter = function(state, getters, { a }, { b }) {}; 44 | 45 | const getters = { 46 | getter, 47 | }; 48 | 49 | const store = { 50 | state: {}, 51 | namespaced: true, 52 | getters: { 53 | getter, 54 | }, 55 | }; 56 | 57 | `, 58 | errors: R.times( 59 | R.always({ 60 | messageId: "avoidRootAssets", 61 | }), 62 | 1, 63 | ), 64 | }, 65 | { 66 | title: "Root state and getters used by actions", 67 | code: ` 68 | const action6 = function (ctx) { 69 | console.log(ctx.rootState) 70 | console.log(ctx.rootGetters) 71 | }; 72 | 73 | const store = { 74 | state: {}, 75 | namespaced: true, 76 | actions: { 77 | action1({ rootState, rootGetters }) {}, 78 | action2({ rootState: rs, rootGetters: rg }) {}, 79 | action3: function({ rootState, rootGetters }) {}, 80 | action4: (ctx) => { 81 | const { rootState, rootGetters } = ctx; 82 | }, 83 | action5(ctx) { 84 | console.log(ctx.rootState); 85 | console.log(ctx.rootGetters); 86 | }, 87 | action6, 88 | }, 89 | }; 90 | `, 91 | errors: R.times( 92 | R.always({ 93 | messageId: "avoidRootAssets", 94 | }), 95 | 12, 96 | ), 97 | }, 98 | ] 99 | 100 | const validCases = [ 101 | { 102 | title: "Getters like objects, but not getters", 103 | code: ` 104 | const store = { 105 | state: {}, 106 | thisIsNotGetters: { 107 | gettersLike(state, getters, rootState) { 108 | 109 | }, 110 | }, 111 | } 112 | `, 113 | }, 114 | { 115 | title: "Valid use of context object", 116 | code: ` 117 | const store = { 118 | state: {}, 119 | namespaced: true, 120 | actions: { 121 | action({ commit, dispatch, state }) {}, 122 | action2(ctx) { 123 | console.log(ctx.state); 124 | console.log(ctx.getters); 125 | }, 126 | }, 127 | }; 128 | `, 129 | }, 130 | ] 131 | 132 | const { valid, invalid } = prepareCases(validCases, invalidCases) 133 | 134 | ruleTester.run("no-root-store-assets", rule, { 135 | valid, 136 | invalid, 137 | }) 138 | -------------------------------------------------------------------------------- /tests/lib/rules/no-root-store-calls.js: -------------------------------------------------------------------------------- 1 | const R = require("ramda") 2 | const { RuleTester } = require("eslint") 3 | const rule = require("../../../lib/rules/no-root-store-calls") 4 | const { prepareCases } = require("../../utils") 5 | 6 | RuleTester.setDefaultConfig({ 7 | parserOptions: { 8 | ecmaVersion: 2018, 9 | sourceType: "module", 10 | }, 11 | }) 12 | 13 | const ruleTester = new RuleTester() 14 | 15 | const invalidCases = [ 16 | { 17 | title: "disapatch global action by calling ctx method", 18 | code: ` 19 | export default function createSomeStore() { 20 | return { 21 | actions: { 22 | action(ctx) { 23 | ctx.commit({ type: 'a' }, { root: true }) 24 | ctx.dispatch('b', null, { root: true }) 25 | const { commit, dispatch } = ctx; 26 | commit('c', null, { root: true }) 27 | dispatch({ type: 'd' }, { root: true }) 28 | }, 29 | }, 30 | } 31 | } 32 | `, 33 | errors: R.times( 34 | R.always({ 35 | messageId: "avoidRootCalls", 36 | }), 37 | 4, 38 | ), 39 | }, 40 | { 41 | title: "commit global mutation by calling destructured method", 42 | code: ` 43 | export default function createSomeStore() { 44 | return { 45 | actions: { 46 | action({ commit, dispatch }) { 47 | commit('b', null, { root: true }) 48 | dispatch({ type: 'a' }, { root: true }) 49 | }, 50 | }, 51 | } 52 | } 53 | `, 54 | errors: R.times( 55 | R.always({ 56 | messageId: "avoidRootCalls", 57 | }), 58 | 2, 59 | ), 60 | }, 61 | ] 62 | 63 | const validCases = [ 64 | { 65 | title: "disapatch local action by calling ctx method", 66 | code: ` 67 | export default function createSomeStore() { 68 | return { 69 | actions: { 70 | action(ctx) { 71 | ctx.commit('1') 72 | }, 73 | }, 74 | } 75 | } 76 | `, 77 | }, 78 | { 79 | title: "commit local mutation by calling destructured method", 80 | code: ` 81 | export default function createSomeStore() { 82 | return { 83 | actions: { 84 | action({ dispatch, commit }) { 85 | dispatch(1, null) 86 | commit({ type: 'm', prop: 1}) 87 | }, 88 | }, 89 | } 90 | } 91 | `, 92 | }, 93 | ] 94 | 95 | const { valid, invalid } = prepareCases(validCases, invalidCases) 96 | 97 | ruleTester.run("no-root-store-calls", rule, { 98 | valid, 99 | invalid, 100 | }) 101 | -------------------------------------------------------------------------------- /tests/lib/rules/require-jsdoc.js: -------------------------------------------------------------------------------- 1 | const { RuleTester } = require("eslint") 2 | const rule = require("../../../lib/rules/require-jsdoc") 3 | const { prepareCases } = require("../../utils") 4 | 5 | RuleTester.setDefaultConfig({ 6 | parserOptions: { 7 | ecmaVersion: 2018, 8 | sourceType: "module", 9 | }, 10 | }) 11 | 12 | const ruleTester = new RuleTester() 13 | 14 | const ERROR_MESSAGE = "Missing JSDoc comment." 15 | const ACTION_PROP = "actions" 16 | 17 | const OPTIONS = [ 18 | { 19 | require: { 20 | VueProps: true, 21 | VuexActions: true, 22 | VuexState: true, 23 | }, 24 | }, 25 | ] 26 | 27 | const getVuexCore = (prop = "getters") => `${prop}: {},` 28 | 29 | // Base test cases are cases that could be both valid and invalid 30 | // depending on the comment before childProp 31 | const createBaseCases = ({ comment }) => [ 32 | { 33 | title: "store object returned by function", 34 | options: OPTIONS, 35 | code: `function createStore() { 36 | return { 37 | ${getVuexCore()} 38 | ${ACTION_PROP}: { 39 | ${comment} 40 | initState() {} 41 | } 42 | }; 43 | }`, 44 | }, 45 | { 46 | title: "inline store object", 47 | options: OPTIONS, 48 | code: ` 49 | new Vuex.Store({ 50 | ${getVuexCore()} 51 | ${ACTION_PROP}: { 52 | ${comment} 53 | initState() {} 54 | } 55 | }); 56 | `, 57 | }, 58 | { 59 | title: "child prop is the state", 60 | options: OPTIONS, 61 | code: `function createStore() { 62 | return { 63 | ${getVuexCore("actions")} 64 | state: { 65 | ${comment} 66 | initState() {} 67 | } 68 | }; 69 | }`, 70 | }, 71 | { 72 | title: "child prop is es6 function shorthand", 73 | options: OPTIONS, 74 | code: `const store = { 75 | ${getVuexCore("getters")} 76 | ${ACTION_PROP}: { 77 | ${comment} 78 | initState() {} 79 | } 80 | };`, 81 | }, 82 | { 83 | title: "child prop is an arrow function", 84 | options: OPTIONS, 85 | code: `const store = { 86 | ${getVuexCore("mutations")} 87 | ${ACTION_PROP}: { 88 | ${comment} 89 | initState: () => {} 90 | } 91 | };`, 92 | }, 93 | { 94 | title: "child prop is a regular function", 95 | options: OPTIONS, 96 | code: `const store = { 97 | ${getVuexCore("modules")} 98 | ${ACTION_PROP}: { 99 | ${comment} 100 | initState: function initState () {} 101 | } 102 | };`, 103 | }, 104 | { 105 | title: "parent prop linked to object with different name", 106 | options: OPTIONS, 107 | code: ` 108 | const awesomeName = { 109 | ${comment} 110 | initState: {} 111 | } 112 | 113 | const store = { 114 | namespaced: true, 115 | ${ACTION_PROP}: awesomeName 116 | };`, 117 | }, 118 | { 119 | title: "parent prop is es6 property shorthand syntax", 120 | options: OPTIONS, 121 | code: ` 122 | const justVariableForSettingUpSomeScope = ''; 123 | const ${ACTION_PROP} = { 124 | ${comment} 125 | initState: {} 126 | } 127 | 128 | const store = { 129 | ${getVuexCore()} 130 | ${ACTION_PROP} 131 | };`, 132 | }, 133 | { 134 | title: "child property linked to identyfier", 135 | options: OPTIONS, 136 | code: ` 137 | const varibaleName = function initState () {}; 138 | const ${ACTION_PROP} = { 139 | ${comment} 140 | initState: varibaleName 141 | }; 142 | 143 | const store = { 144 | ${getVuexCore()} 145 | ${ACTION_PROP} 146 | };`, 147 | }, 148 | { 149 | title: "spread childs", 150 | options: OPTIONS, 151 | code: ` 152 | const getProps = () => {}; 153 | 154 | const store = { 155 | ${getVuexCore()} 156 | ${ACTION_PROP}: { 157 | ...getProps(), 158 | ${comment} 159 | initState() {}, 160 | } 161 | };`, 162 | }, 163 | { 164 | title: "deep nested store object", 165 | options: OPTIONS, 166 | code: ` 167 | export const mutations = {}; 168 | 169 | const ${ACTION_PROP} = { 170 | ${comment} 171 | initState: function initState () {} 172 | }; 173 | export default function createSsrStore() { 174 | return function nestedFunctions() { 175 | return { 176 | ${getVuexCore()} 177 | ${ACTION_PROP}, 178 | mutations 179 | }; 180 | } 181 | };`, 182 | }, 183 | { 184 | title: "state is a function", 185 | options: OPTIONS, 186 | code: ` 187 | function initialState() { 188 | return { 189 | ${comment} 190 | a: '' 191 | } 192 | } 193 | 194 | const store = { 195 | ${getVuexCore()} 196 | state: initialState, 197 | getters: {} 198 | }`, 199 | }, 200 | { 201 | title: "vue props", 202 | options: OPTIONS, 203 | code: ` 204 | export default { 205 | data() {}, 206 | props: { 207 | ${comment} 208 | propA: { 209 | 210 | } 211 | } 212 | } 213 | `, 214 | }, 215 | ] 216 | 217 | const baseValidCases = createBaseCases({ comment: "/** Simple valid jsdoc */" }) 218 | const baseInvalidCases = createBaseCases({ comment: "" }).map(testCase => ({ 219 | ...testCase, 220 | errors: [ 221 | { 222 | message: ERROR_MESSAGE, 223 | }, 224 | ], 225 | })) 226 | 227 | /** 228 | * Specify `only: true` prop. for stanalone testcase run. 229 | * Specify `skip: true` prop. to skip testcase 230 | */ 231 | const validCases = [ 232 | ...baseValidCases, 233 | { 234 | title: "empty parent", 235 | code: `const store = { 236 | ${getVuexCore()} 237 | ${ACTION_PROP}: {} 238 | };`, 239 | options: OPTIONS, 240 | }, 241 | { 242 | title: "parent prop default import", 243 | code: ` 244 | import ${ACTION_PROP} from 'store'; 245 | const store = { 246 | ${getVuexCore()} 247 | ${ACTION_PROP}, 248 | };`, 249 | options: OPTIONS, 250 | }, 251 | { 252 | title: "parent prop named import", 253 | code: ` 254 | import { ${ACTION_PROP} } from 'store'; 255 | const store = { 256 | ${getVuexCore()} 257 | ${ACTION_PROP}, 258 | };`, 259 | options: OPTIONS, 260 | }, 261 | { 262 | title: "Object has actions key, but it's not vuex store", 263 | code: ` 264 | const store = { 265 | justSomeKey: 'asd', 266 | ${ACTION_PROP}: { 267 | someKey() {}, 268 | } 269 | };`, 270 | options: OPTIONS, 271 | }, 272 | { 273 | title: "Actions is not an Object", 274 | code: ` 275 | const store = { 276 | ${getVuexCore("namespaced")} 277 | ${ACTION_PROP}: "just string" 278 | };`, 279 | options: OPTIONS, 280 | }, 281 | { 282 | title: "Should not throw error for store like objects", 283 | code: ` 284 | const state = { 285 | asd: 111 286 | }; 287 | 288 | const storeLikeObject = { 289 | commit: {}, 290 | getters: {}, 291 | state, 292 | rootGetters: {}, 293 | };`, 294 | options: OPTIONS, 295 | }, 296 | { 297 | title: "Should not throw error if only state and getters provided", 298 | code: ` 299 | const state = { 300 | asd: 111 301 | }; 302 | 303 | const storeLikeObject = { 304 | getters: {}, 305 | state 306 | };`, 307 | options: OPTIONS, 308 | }, 309 | { 310 | title: "Should not throw error when desctucturing state in action", 311 | code: ` 312 | const state = { 313 | asd: 1 314 | }; 315 | 316 | export default function a() { 317 | return { 318 | state: {}, 319 | actions: { 320 | /** jsdoc */ 321 | action({ state, getters }){} 322 | }, 323 | }; 324 | }`, 325 | options: OPTIONS, 326 | }, 327 | ] 328 | 329 | const invalidCases = [ 330 | ...baseInvalidCases, 331 | { 332 | title: "jsdoc is empty comment line", 333 | code: `const store = { 334 | ${getVuexCore()} 335 | ${ACTION_PROP}: { 336 | // 337 | initState() {}, 338 | } 339 | };`, 340 | errors: [ 341 | { 342 | message: ERROR_MESSAGE, 343 | }, 344 | ], 345 | options: OPTIONS, 346 | }, 347 | { 348 | title: "jsdoc is empty comment block", 349 | code: `const store = { 350 | ${getVuexCore()} 351 | ${ACTION_PROP}: { 352 | /* */ 353 | initState() {}, 354 | } 355 | };`, 356 | errors: [ 357 | { 358 | message: ERROR_MESSAGE, 359 | }, 360 | ], 361 | options: OPTIONS, 362 | }, 363 | 364 | { 365 | title: "state + actions", 366 | code: `function createStore() { 367 | return { 368 | ${getVuexCore("actions")} 369 | state: { 370 | someValue: '', 371 | }, 372 | ${ACTION_PROP}: { 373 | initState() {} 374 | } 375 | }; 376 | }`, 377 | errors: [ 378 | { 379 | message: ERROR_MESSAGE, 380 | }, 381 | { 382 | message: ERROR_MESSAGE, 383 | }, 384 | ], 385 | options: OPTIONS, 386 | }, 387 | { 388 | title: "Only state rule enabled", 389 | code: `function createStore() { 390 | return { 391 | ${getVuexCore("actions")} 392 | state: { 393 | someValue: '', 394 | }, 395 | ${ACTION_PROP}: { 396 | initState() {} 397 | } 398 | }; 399 | }`, 400 | errors: [ 401 | { 402 | message: ERROR_MESSAGE, 403 | }, 404 | ], 405 | options: [ 406 | { 407 | require: { 408 | VuexActions: false, 409 | VuexState: true, 410 | }, 411 | }, 412 | ], 413 | }, 414 | ] 415 | 416 | const { valid, invalid } = prepareCases(validCases, invalidCases) 417 | 418 | ruleTester.run("require-jsdoc", rule, { 419 | valid, 420 | invalid, 421 | }) 422 | -------------------------------------------------------------------------------- /tests/utils.js: -------------------------------------------------------------------------------- 1 | const { isEmpty, map, omit, filter } = require("ramda") 2 | 3 | /** 4 | * Prepare testcases by filtering using skip and only props. 5 | * @param {Array} valid - valid testcases, each test may contain skip or only property 6 | * @param {Array} invalid - valid testcases, each test may contain skip or only property 7 | * @return {{valid: Array, invalid: Array}} 8 | */ 9 | function prepareCases(valid = [], invalid) { 10 | const filterStandalone = filter(({ only = false }) => only) 11 | const filterSkiped = filter(({ skip = false }) => !skip) 12 | const omitProps = map(omit(["only", "skip", "title"])) 13 | 14 | const standaloneValidCases = filterStandalone(valid) 15 | const standaloneInvalidCases = filterStandalone(invalid) 16 | 17 | const prepareReturnValue = (v, i) => ({ 18 | valid: omitProps(filterSkiped(v)), 19 | invalid: omitProps(filterSkiped(i)), 20 | }) 21 | 22 | // there are no standalone testcases 23 | if (isEmpty(standaloneValidCases) && isEmpty(standaloneInvalidCases)) { 24 | return prepareReturnValue(valid, invalid) 25 | } 26 | 27 | return prepareReturnValue(standaloneValidCases, standaloneInvalidCases) 28 | } 29 | 30 | module.exports = { 31 | prepareCases, 32 | } 33 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@7.0.0-beta.44": 6 | version "7.0.0-beta.44" 7 | resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9" 8 | dependencies: 9 | "@babel/highlight" "7.0.0-beta.44" 10 | 11 | "@babel/generator@7.0.0-beta.44": 12 | version "7.0.0-beta.44" 13 | resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42" 14 | dependencies: 15 | "@babel/types" "7.0.0-beta.44" 16 | jsesc "^2.5.1" 17 | lodash "^4.2.0" 18 | source-map "^0.5.0" 19 | trim-right "^1.0.1" 20 | 21 | "@babel/helper-function-name@7.0.0-beta.44": 22 | version "7.0.0-beta.44" 23 | resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd" 24 | dependencies: 25 | "@babel/helper-get-function-arity" "7.0.0-beta.44" 26 | "@babel/template" "7.0.0-beta.44" 27 | "@babel/types" "7.0.0-beta.44" 28 | 29 | "@babel/helper-get-function-arity@7.0.0-beta.44": 30 | version "7.0.0-beta.44" 31 | resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15" 32 | dependencies: 33 | "@babel/types" "7.0.0-beta.44" 34 | 35 | "@babel/helper-split-export-declaration@7.0.0-beta.44": 36 | version "7.0.0-beta.44" 37 | resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc" 38 | dependencies: 39 | "@babel/types" "7.0.0-beta.44" 40 | 41 | "@babel/highlight@7.0.0-beta.44": 42 | version "7.0.0-beta.44" 43 | resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5" 44 | dependencies: 45 | chalk "^2.0.0" 46 | esutils "^2.0.2" 47 | js-tokens "^3.0.0" 48 | 49 | "@babel/template@7.0.0-beta.44": 50 | version "7.0.0-beta.44" 51 | resolved "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f" 52 | dependencies: 53 | "@babel/code-frame" "7.0.0-beta.44" 54 | "@babel/types" "7.0.0-beta.44" 55 | babylon "7.0.0-beta.44" 56 | lodash "^4.2.0" 57 | 58 | "@babel/traverse@7.0.0-beta.44": 59 | version "7.0.0-beta.44" 60 | resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966" 61 | dependencies: 62 | "@babel/code-frame" "7.0.0-beta.44" 63 | "@babel/generator" "7.0.0-beta.44" 64 | "@babel/helper-function-name" "7.0.0-beta.44" 65 | "@babel/helper-split-export-declaration" "7.0.0-beta.44" 66 | "@babel/types" "7.0.0-beta.44" 67 | babylon "7.0.0-beta.44" 68 | debug "^3.1.0" 69 | globals "^11.1.0" 70 | invariant "^2.2.0" 71 | lodash "^4.2.0" 72 | 73 | "@babel/types@7.0.0-beta.44": 74 | version "7.0.0-beta.44" 75 | resolved "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757" 76 | dependencies: 77 | esutils "^2.0.2" 78 | lodash "^4.2.0" 79 | to-fast-properties "^2.0.0" 80 | 81 | acorn-jsx@^4.1.1: 82 | version "4.1.1" 83 | resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" 84 | dependencies: 85 | acorn "^5.0.3" 86 | 87 | acorn@^5.0.3, acorn@^5.6.0: 88 | version "5.7.4" 89 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" 90 | 91 | ajv-keywords@^3.0.0: 92 | version "3.2.0" 93 | resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" 94 | 95 | ajv@^6.0.1, ajv@^6.5.0: 96 | version "6.5.2" 97 | resolved "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz#678495f9b82f7cca6be248dd92f59bff5e1f4360" 98 | dependencies: 99 | fast-deep-equal "^2.0.1" 100 | fast-json-stable-stringify "^2.0.0" 101 | json-schema-traverse "^0.4.1" 102 | uri-js "^4.2.1" 103 | 104 | ansi-escapes@^3.0.0: 105 | version "3.1.0" 106 | resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" 107 | 108 | ansi-regex@^2.0.0: 109 | version "2.1.1" 110 | resolved "http://sinopia.app.s/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 111 | 112 | ansi-regex@^3.0.0: 113 | version "3.0.0" 114 | resolved "http://sinopia.app.s/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 115 | 116 | ansi-styles@^2.2.1: 117 | version "2.2.1" 118 | resolved "http://sinopia.app.s/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 119 | 120 | ansi-styles@^3.2.1: 121 | version "3.2.1" 122 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 123 | dependencies: 124 | color-convert "^1.9.0" 125 | 126 | argparse@^1.0.7: 127 | version "1.0.10" 128 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 129 | dependencies: 130 | sprintf-js "~1.0.2" 131 | 132 | array-union@^1.0.1: 133 | version "1.0.2" 134 | resolved "http://sinopia.app.s/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 135 | dependencies: 136 | array-uniq "^1.0.1" 137 | 138 | array-uniq@^1.0.1: 139 | version "1.0.3" 140 | resolved "http://sinopia.app.s/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 141 | 142 | arrify@^1.0.0: 143 | version "1.0.1" 144 | resolved "http://sinopia.app.s/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 145 | 146 | babel-code-frame@^6.26.0: 147 | version "6.26.0" 148 | resolved "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" 149 | dependencies: 150 | chalk "^1.1.3" 151 | esutils "^2.0.2" 152 | js-tokens "^3.0.2" 153 | 154 | babel-eslint@^8.2.6: 155 | version "8.2.6" 156 | resolved "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz#6270d0c73205628067c0f7ae1693a9e797acefd9" 157 | dependencies: 158 | "@babel/code-frame" "7.0.0-beta.44" 159 | "@babel/traverse" "7.0.0-beta.44" 160 | "@babel/types" "7.0.0-beta.44" 161 | babylon "7.0.0-beta.44" 162 | eslint-scope "3.7.1" 163 | eslint-visitor-keys "^1.0.0" 164 | 165 | babylon@7.0.0-beta.44: 166 | version "7.0.0-beta.44" 167 | resolved "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d" 168 | 169 | balanced-match@^1.0.0: 170 | version "1.0.0" 171 | resolved "http://sinopia.app.s/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 172 | 173 | brace-expansion@^1.1.7: 174 | version "1.1.11" 175 | resolved "http://sinopia.app.s/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 176 | dependencies: 177 | balanced-match "^1.0.0" 178 | concat-map "0.0.1" 179 | 180 | browser-stdout@1.3.0: 181 | version "1.3.0" 182 | resolved "http://sinopia.app.s/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" 183 | 184 | builtin-modules@^1.0.0: 185 | version "1.1.1" 186 | resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 187 | 188 | caller-path@^0.1.0: 189 | version "0.1.0" 190 | resolved "http://sinopia.app.s/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" 191 | dependencies: 192 | callsites "^0.2.0" 193 | 194 | callsites@^0.2.0: 195 | version "0.2.0" 196 | resolved "http://sinopia.app.s/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" 197 | 198 | chalk@^1.1.3: 199 | version "1.1.3" 200 | resolved "http://sinopia.app.s/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 201 | dependencies: 202 | ansi-styles "^2.2.1" 203 | escape-string-regexp "^1.0.2" 204 | has-ansi "^2.0.0" 205 | strip-ansi "^3.0.0" 206 | supports-color "^2.0.0" 207 | 208 | chalk@^2.0.0, chalk@^2.1.0: 209 | version "2.4.1" 210 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" 211 | dependencies: 212 | ansi-styles "^3.2.1" 213 | escape-string-regexp "^1.0.5" 214 | supports-color "^5.3.0" 215 | 216 | chardet@^0.4.0: 217 | version "0.4.2" 218 | resolved "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" 219 | 220 | circular-json@^0.3.1: 221 | version "0.3.3" 222 | resolved "http://sinopia.app.s/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" 223 | 224 | cli-cursor@^2.1.0: 225 | version "2.1.0" 226 | resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" 227 | dependencies: 228 | restore-cursor "^2.0.0" 229 | 230 | cli-width@^2.0.0: 231 | version "2.2.0" 232 | resolved "http://sinopia.app.s/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" 233 | 234 | color-convert@^1.9.0: 235 | version "1.9.2" 236 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" 237 | dependencies: 238 | color-name "1.1.1" 239 | 240 | color-name@1.1.1: 241 | version "1.1.1" 242 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" 243 | 244 | commander@2.9.0: 245 | version "2.9.0" 246 | resolved "http://sinopia.app.s/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 247 | dependencies: 248 | graceful-readlink ">= 1.0.0" 249 | 250 | concat-map@0.0.1: 251 | version "0.0.1" 252 | resolved "http://sinopia.app.s/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 253 | 254 | contains-path@^0.1.0: 255 | version "0.1.0" 256 | resolved "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" 257 | 258 | cross-spawn@^6.0.5: 259 | version "6.0.5" 260 | resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 261 | dependencies: 262 | nice-try "^1.0.4" 263 | path-key "^2.0.1" 264 | semver "^5.5.0" 265 | shebang-command "^1.2.0" 266 | which "^1.2.9" 267 | 268 | debug@2.6.8: 269 | version "2.6.8" 270 | resolved "http://sinopia.app.s/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" 271 | dependencies: 272 | ms "2.0.0" 273 | 274 | debug@^2.6.8, debug@^2.6.9: 275 | version "2.6.9" 276 | resolved "http://sinopia.app.s/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 277 | dependencies: 278 | ms "2.0.0" 279 | 280 | debug@^3.1.0: 281 | version "3.1.0" 282 | resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 283 | dependencies: 284 | ms "2.0.0" 285 | 286 | deep-is@~0.1.3: 287 | version "0.1.3" 288 | resolved "http://sinopia.app.s/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 289 | 290 | define-properties@^1.1.2: 291 | version "1.1.2" 292 | resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" 293 | dependencies: 294 | foreach "^2.0.5" 295 | object-keys "^1.0.8" 296 | 297 | del@^2.0.2: 298 | version "2.2.2" 299 | resolved "http://sinopia.app.s/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" 300 | dependencies: 301 | globby "^5.0.0" 302 | is-path-cwd "^1.0.0" 303 | is-path-in-cwd "^1.0.0" 304 | object-assign "^4.0.1" 305 | pify "^2.0.0" 306 | pinkie-promise "^2.0.0" 307 | rimraf "^2.2.8" 308 | 309 | diff@3.2.0: 310 | version "3.2.0" 311 | resolved "http://sinopia.app.s/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" 312 | 313 | doctrine@1.5.0: 314 | version "1.5.0" 315 | resolved "http://sinopia.app.s/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" 316 | dependencies: 317 | esutils "^2.0.2" 318 | isarray "^1.0.0" 319 | 320 | doctrine@^2.1.0: 321 | version "2.1.0" 322 | resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" 323 | dependencies: 324 | esutils "^2.0.2" 325 | 326 | error-ex@^1.2.0: 327 | version "1.3.2" 328 | resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 329 | dependencies: 330 | is-arrayish "^0.2.1" 331 | 332 | es-abstract@^1.10.0, es-abstract@^1.6.1: 333 | version "1.12.0" 334 | resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" 335 | dependencies: 336 | es-to-primitive "^1.1.1" 337 | function-bind "^1.1.1" 338 | has "^1.0.1" 339 | is-callable "^1.1.3" 340 | is-regex "^1.0.4" 341 | 342 | es-to-primitive@^1.1.1: 343 | version "1.1.1" 344 | resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" 345 | dependencies: 346 | is-callable "^1.1.1" 347 | is-date-object "^1.0.1" 348 | is-symbol "^1.0.1" 349 | 350 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 351 | version "1.0.5" 352 | resolved "http://sinopia.app.s/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 353 | 354 | eslint-config-airbnb-base@^13.0.0: 355 | version "13.0.0" 356 | resolved "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.0.0.tgz#2ee6279c4891128e49d6445b24aa13c2d1a21450" 357 | dependencies: 358 | eslint-restricted-globals "^0.1.1" 359 | object.assign "^4.1.0" 360 | object.entries "^1.0.4" 361 | 362 | eslint-config-prettier@^2.9.0: 363 | version "2.9.0" 364 | resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" 365 | dependencies: 366 | get-stdin "^5.0.1" 367 | 368 | eslint-import-resolver-node@^0.3.1: 369 | version "0.3.2" 370 | resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" 371 | dependencies: 372 | debug "^2.6.9" 373 | resolve "^1.5.0" 374 | 375 | eslint-module-utils@^2.2.0: 376 | version "2.2.0" 377 | resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" 378 | dependencies: 379 | debug "^2.6.8" 380 | pkg-dir "^1.0.0" 381 | 382 | eslint-plugin-import@^2.13.0: 383 | version "2.13.0" 384 | resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz#df24f241175e312d91662dc91ca84064caec14ed" 385 | dependencies: 386 | contains-path "^0.1.0" 387 | debug "^2.6.8" 388 | doctrine "1.5.0" 389 | eslint-import-resolver-node "^0.3.1" 390 | eslint-module-utils "^2.2.0" 391 | has "^1.0.1" 392 | lodash "^4.17.4" 393 | minimatch "^3.0.3" 394 | read-pkg-up "^2.0.0" 395 | resolve "^1.6.0" 396 | 397 | eslint-plugin-prettier@^2.6.2: 398 | version "2.6.2" 399 | resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.2.tgz#71998c60aedfa2141f7bfcbf9d1c459bf98b4fad" 400 | dependencies: 401 | fast-diff "^1.1.1" 402 | jest-docblock "^21.0.0" 403 | 404 | eslint-restricted-globals@^0.1.1: 405 | version "0.1.1" 406 | resolved "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" 407 | 408 | eslint-scope@3.7.1: 409 | version "3.7.1" 410 | resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" 411 | dependencies: 412 | esrecurse "^4.1.0" 413 | estraverse "^4.1.1" 414 | 415 | eslint-scope@^4.0.0: 416 | version "4.0.0" 417 | resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" 418 | dependencies: 419 | esrecurse "^4.1.0" 420 | estraverse "^4.1.1" 421 | 422 | eslint-utils@^1.3.1: 423 | version "1.4.3" 424 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" 425 | dependencies: 426 | eslint-visitor-keys "^1.1.0" 427 | 428 | eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: 429 | version "1.1.0" 430 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" 431 | 432 | eslint@^5.3.0: 433 | version "5.3.0" 434 | resolved "https://registry.npmjs.org/eslint/-/eslint-5.3.0.tgz#53695aca5213968aacdf970ccb231e42a2b285f8" 435 | dependencies: 436 | ajv "^6.5.0" 437 | babel-code-frame "^6.26.0" 438 | chalk "^2.1.0" 439 | cross-spawn "^6.0.5" 440 | debug "^3.1.0" 441 | doctrine "^2.1.0" 442 | eslint-scope "^4.0.0" 443 | eslint-utils "^1.3.1" 444 | eslint-visitor-keys "^1.0.0" 445 | espree "^4.0.0" 446 | esquery "^1.0.1" 447 | esutils "^2.0.2" 448 | file-entry-cache "^2.0.0" 449 | functional-red-black-tree "^1.0.1" 450 | glob "^7.1.2" 451 | globals "^11.7.0" 452 | ignore "^4.0.2" 453 | imurmurhash "^0.1.4" 454 | inquirer "^5.2.0" 455 | is-resolvable "^1.1.0" 456 | js-yaml "^3.11.0" 457 | json-stable-stringify-without-jsonify "^1.0.1" 458 | levn "^0.3.0" 459 | lodash "^4.17.5" 460 | minimatch "^3.0.4" 461 | mkdirp "^0.5.1" 462 | natural-compare "^1.4.0" 463 | optionator "^0.8.2" 464 | path-is-inside "^1.0.2" 465 | pluralize "^7.0.0" 466 | progress "^2.0.0" 467 | regexpp "^2.0.0" 468 | require-uncached "^1.0.3" 469 | semver "^5.5.0" 470 | string.prototype.matchall "^2.0.0" 471 | strip-ansi "^4.0.0" 472 | strip-json-comments "^2.0.1" 473 | table "^4.0.3" 474 | text-table "^0.2.0" 475 | 476 | espree@^4.0.0: 477 | version "4.0.0" 478 | resolved "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634" 479 | dependencies: 480 | acorn "^5.6.0" 481 | acorn-jsx "^4.1.1" 482 | 483 | esprima@^4.0.0: 484 | version "4.0.1" 485 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 486 | 487 | esquery@^1.0.1: 488 | version "1.0.1" 489 | resolved "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" 490 | dependencies: 491 | estraverse "^4.0.0" 492 | 493 | esrecurse@^4.1.0: 494 | version "4.2.1" 495 | resolved "http://sinopia.app.s/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" 496 | dependencies: 497 | estraverse "^4.1.0" 498 | 499 | estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: 500 | version "4.2.0" 501 | resolved "http://sinopia.app.s/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" 502 | 503 | esutils@^2.0.2: 504 | version "2.0.2" 505 | resolved "http://sinopia.app.s/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 506 | 507 | external-editor@^2.1.0: 508 | version "2.2.0" 509 | resolved "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" 510 | dependencies: 511 | chardet "^0.4.0" 512 | iconv-lite "^0.4.17" 513 | tmp "^0.0.33" 514 | 515 | fast-deep-equal@^2.0.1: 516 | version "2.0.1" 517 | resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" 518 | 519 | fast-diff@^1.1.1: 520 | version "1.1.2" 521 | resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" 522 | 523 | fast-json-stable-stringify@^2.0.0: 524 | version "2.0.0" 525 | resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" 526 | 527 | fast-levenshtein@~2.0.4: 528 | version "2.0.6" 529 | resolved "http://sinopia.app.s/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 530 | 531 | figures@^2.0.0: 532 | version "2.0.0" 533 | resolved "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" 534 | dependencies: 535 | escape-string-regexp "^1.0.5" 536 | 537 | file-entry-cache@^2.0.0: 538 | version "2.0.0" 539 | resolved "http://sinopia.app.s/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" 540 | dependencies: 541 | flat-cache "^1.2.1" 542 | object-assign "^4.0.1" 543 | 544 | find-up@^1.0.0: 545 | version "1.1.2" 546 | resolved "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" 547 | dependencies: 548 | path-exists "^2.0.0" 549 | pinkie-promise "^2.0.0" 550 | 551 | find-up@^2.0.0: 552 | version "2.1.0" 553 | resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" 554 | dependencies: 555 | locate-path "^2.0.0" 556 | 557 | flat-cache@^1.2.1: 558 | version "1.3.0" 559 | resolved "http://sinopia.app.s/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" 560 | dependencies: 561 | circular-json "^0.3.1" 562 | del "^2.0.2" 563 | graceful-fs "^4.1.2" 564 | write "^0.2.1" 565 | 566 | foreach@^2.0.5: 567 | version "2.0.5" 568 | resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" 569 | 570 | fs.realpath@^1.0.0: 571 | version "1.0.0" 572 | resolved "http://sinopia.app.s/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 573 | 574 | function-bind@^1.1.0, function-bind@^1.1.1: 575 | version "1.1.1" 576 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 577 | 578 | functional-red-black-tree@^1.0.1: 579 | version "1.0.1" 580 | resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 581 | 582 | get-stdin@^5.0.1: 583 | version "5.0.1" 584 | resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" 585 | 586 | glob@7.1.1: 587 | version "7.1.1" 588 | resolved "http://sinopia.app.s/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 589 | dependencies: 590 | fs.realpath "^1.0.0" 591 | inflight "^1.0.4" 592 | inherits "2" 593 | minimatch "^3.0.2" 594 | once "^1.3.0" 595 | path-is-absolute "^1.0.0" 596 | 597 | glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: 598 | version "7.1.2" 599 | resolved "http://sinopia.app.s/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 600 | dependencies: 601 | fs.realpath "^1.0.0" 602 | inflight "^1.0.4" 603 | inherits "2" 604 | minimatch "^3.0.4" 605 | once "^1.3.0" 606 | path-is-absolute "^1.0.0" 607 | 608 | globals@^11.1.0, globals@^11.7.0: 609 | version "11.7.0" 610 | resolved "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" 611 | 612 | globby@^5.0.0: 613 | version "5.0.0" 614 | resolved "http://sinopia.app.s/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" 615 | dependencies: 616 | array-union "^1.0.1" 617 | arrify "^1.0.0" 618 | glob "^7.0.3" 619 | object-assign "^4.0.1" 620 | pify "^2.0.0" 621 | pinkie-promise "^2.0.0" 622 | 623 | graceful-fs@^4.1.2: 624 | version "4.1.11" 625 | resolved "http://sinopia.app.s/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 626 | 627 | "graceful-readlink@>= 1.0.0": 628 | version "1.0.1" 629 | resolved "http://sinopia.app.s/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 630 | 631 | growl@1.9.2: 632 | version "1.9.2" 633 | resolved "http://sinopia.app.s/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" 634 | 635 | has-ansi@^2.0.0: 636 | version "2.0.0" 637 | resolved "http://sinopia.app.s/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 638 | dependencies: 639 | ansi-regex "^2.0.0" 640 | 641 | has-flag@^1.0.0: 642 | version "1.0.0" 643 | resolved "http://sinopia.app.s/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 644 | 645 | has-flag@^3.0.0: 646 | version "3.0.0" 647 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 648 | 649 | has-symbols@^1.0.0: 650 | version "1.0.0" 651 | resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" 652 | 653 | has@^1.0.1: 654 | version "1.0.3" 655 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 656 | dependencies: 657 | function-bind "^1.1.1" 658 | 659 | he@1.1.1: 660 | version "1.1.1" 661 | resolved "http://sinopia.app.s/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" 662 | 663 | hosted-git-info@^2.1.4: 664 | version "2.7.1" 665 | resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" 666 | 667 | iconv-lite@^0.4.17: 668 | version "0.4.23" 669 | resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" 670 | dependencies: 671 | safer-buffer ">= 2.1.2 < 3" 672 | 673 | ignore@^4.0.2: 674 | version "4.0.3" 675 | resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.3.tgz#e2d58c9654d75b542529fa28d80ac95b29e4f467" 676 | 677 | imurmurhash@^0.1.4: 678 | version "0.1.4" 679 | resolved "http://sinopia.app.s/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 680 | 681 | inflight@^1.0.4: 682 | version "1.0.6" 683 | resolved "http://sinopia.app.s/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 684 | dependencies: 685 | once "^1.3.0" 686 | wrappy "1" 687 | 688 | inherits@2: 689 | version "2.0.3" 690 | resolved "http://sinopia.app.s/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 691 | 692 | inquirer@^5.2.0: 693 | version "5.2.0" 694 | resolved "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726" 695 | dependencies: 696 | ansi-escapes "^3.0.0" 697 | chalk "^2.0.0" 698 | cli-cursor "^2.1.0" 699 | cli-width "^2.0.0" 700 | external-editor "^2.1.0" 701 | figures "^2.0.0" 702 | lodash "^4.3.0" 703 | mute-stream "0.0.7" 704 | run-async "^2.2.0" 705 | rxjs "^5.5.2" 706 | string-width "^2.1.0" 707 | strip-ansi "^4.0.0" 708 | through "^2.3.6" 709 | 710 | invariant@^2.2.0: 711 | version "2.2.4" 712 | resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" 713 | dependencies: 714 | loose-envify "^1.0.0" 715 | 716 | is-arrayish@^0.2.1: 717 | version "0.2.1" 718 | resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 719 | 720 | is-builtin-module@^1.0.0: 721 | version "1.0.0" 722 | resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" 723 | dependencies: 724 | builtin-modules "^1.0.0" 725 | 726 | is-callable@^1.1.1, is-callable@^1.1.3: 727 | version "1.1.4" 728 | resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" 729 | 730 | is-date-object@^1.0.1: 731 | version "1.0.1" 732 | resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" 733 | 734 | is-fullwidth-code-point@^2.0.0: 735 | version "2.0.0" 736 | resolved "http://sinopia.app.s/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 737 | 738 | is-path-cwd@^1.0.0: 739 | version "1.0.0" 740 | resolved "http://sinopia.app.s/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" 741 | 742 | is-path-in-cwd@^1.0.0: 743 | version "1.0.1" 744 | resolved "http://sinopia.app.s/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" 745 | dependencies: 746 | is-path-inside "^1.0.0" 747 | 748 | is-path-inside@^1.0.0: 749 | version "1.0.1" 750 | resolved "http://sinopia.app.s/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" 751 | dependencies: 752 | path-is-inside "^1.0.1" 753 | 754 | is-promise@^2.1.0: 755 | version "2.1.0" 756 | resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 757 | 758 | is-regex@^1.0.4: 759 | version "1.0.4" 760 | resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" 761 | dependencies: 762 | has "^1.0.1" 763 | 764 | is-resolvable@^1.1.0: 765 | version "1.1.0" 766 | resolved "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" 767 | 768 | is-symbol@^1.0.1: 769 | version "1.0.1" 770 | resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" 771 | 772 | isarray@^1.0.0: 773 | version "1.0.0" 774 | resolved "http://sinopia.app.s/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 775 | 776 | isexe@^2.0.0: 777 | version "2.0.0" 778 | resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 779 | 780 | jest-docblock@^21.0.0: 781 | version "21.2.0" 782 | resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" 783 | 784 | js-tokens@^3.0.0, js-tokens@^3.0.2: 785 | version "3.0.2" 786 | resolved "http://sinopia.app.s/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 787 | 788 | "js-tokens@^3.0.0 || ^4.0.0": 789 | version "4.0.0" 790 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 791 | 792 | js-yaml@^3.11.0: 793 | version "3.13.1" 794 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 795 | dependencies: 796 | argparse "^1.0.7" 797 | esprima "^4.0.0" 798 | 799 | jsesc@^2.5.1: 800 | version "2.5.1" 801 | resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" 802 | 803 | json-schema-traverse@^0.4.1: 804 | version "0.4.1" 805 | resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 806 | 807 | json-stable-stringify-without-jsonify@^1.0.1: 808 | version "1.0.1" 809 | resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 810 | 811 | json3@3.3.2: 812 | version "3.3.2" 813 | resolved "http://sinopia.app.s/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" 814 | 815 | levn@^0.3.0, levn@~0.3.0: 816 | version "0.3.0" 817 | resolved "http://sinopia.app.s/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 818 | dependencies: 819 | prelude-ls "~1.1.2" 820 | type-check "~0.3.2" 821 | 822 | load-json-file@^2.0.0: 823 | version "2.0.0" 824 | resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" 825 | dependencies: 826 | graceful-fs "^4.1.2" 827 | parse-json "^2.2.0" 828 | pify "^2.0.0" 829 | strip-bom "^3.0.0" 830 | 831 | locate-path@^2.0.0: 832 | version "2.0.0" 833 | resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" 834 | dependencies: 835 | p-locate "^2.0.0" 836 | path-exists "^3.0.0" 837 | 838 | lodash._baseassign@^3.0.0: 839 | version "3.2.0" 840 | resolved "http://sinopia.app.s/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" 841 | dependencies: 842 | lodash._basecopy "^3.0.0" 843 | lodash.keys "^3.0.0" 844 | 845 | lodash._basecopy@^3.0.0: 846 | version "3.0.1" 847 | resolved "http://sinopia.app.s/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" 848 | 849 | lodash._basecreate@^3.0.0: 850 | version "3.0.3" 851 | resolved "http://sinopia.app.s/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" 852 | 853 | lodash._getnative@^3.0.0: 854 | version "3.9.1" 855 | resolved "http://sinopia.app.s/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" 856 | 857 | lodash._isiterateecall@^3.0.0: 858 | version "3.0.9" 859 | resolved "http://sinopia.app.s/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" 860 | 861 | lodash.create@3.1.1: 862 | version "3.1.1" 863 | resolved "http://sinopia.app.s/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" 864 | dependencies: 865 | lodash._baseassign "^3.0.0" 866 | lodash._basecreate "^3.0.0" 867 | lodash._isiterateecall "^3.0.0" 868 | 869 | lodash.isarguments@^3.0.0: 870 | version "3.1.0" 871 | resolved "http://sinopia.app.s/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 872 | 873 | lodash.isarray@^3.0.0: 874 | version "3.0.4" 875 | resolved "http://sinopia.app.s/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" 876 | 877 | lodash.keys@^3.0.0: 878 | version "3.1.2" 879 | resolved "http://sinopia.app.s/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" 880 | dependencies: 881 | lodash._getnative "^3.0.0" 882 | lodash.isarguments "^3.0.0" 883 | lodash.isarray "^3.0.0" 884 | 885 | lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0: 886 | version "4.17.21" 887 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 888 | 889 | loose-envify@^1.0.0: 890 | version "1.4.0" 891 | resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 892 | dependencies: 893 | js-tokens "^3.0.0 || ^4.0.0" 894 | 895 | mimic-fn@^1.0.0: 896 | version "1.2.0" 897 | resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" 898 | 899 | minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: 900 | version "3.0.4" 901 | resolved "http://sinopia.app.s/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 902 | dependencies: 903 | brace-expansion "^1.1.7" 904 | 905 | minimist@0.0.8: 906 | version "0.0.8" 907 | resolved "http://sinopia.app.s/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 908 | 909 | mkdirp@0.5.1, mkdirp@^0.5.1: 910 | version "0.5.1" 911 | resolved "http://sinopia.app.s/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 912 | dependencies: 913 | minimist "0.0.8" 914 | 915 | mocha@^3.1.2: 916 | version "3.5.3" 917 | resolved "http://sinopia.app.s/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" 918 | dependencies: 919 | browser-stdout "1.3.0" 920 | commander "2.9.0" 921 | debug "2.6.8" 922 | diff "3.2.0" 923 | escape-string-regexp "1.0.5" 924 | glob "7.1.1" 925 | growl "1.9.2" 926 | he "1.1.1" 927 | json3 "3.3.2" 928 | lodash.create "3.1.1" 929 | mkdirp "0.5.1" 930 | supports-color "3.1.2" 931 | 932 | ms@2.0.0: 933 | version "2.0.0" 934 | resolved "http://sinopia.app.s/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 935 | 936 | mute-stream@0.0.7: 937 | version "0.0.7" 938 | resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" 939 | 940 | natural-compare@^1.4.0: 941 | version "1.4.0" 942 | resolved "http://sinopia.app.s/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 943 | 944 | nice-try@^1.0.4: 945 | version "1.0.4" 946 | resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" 947 | 948 | normalize-package-data@^2.3.2: 949 | version "2.4.0" 950 | resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" 951 | dependencies: 952 | hosted-git-info "^2.1.4" 953 | is-builtin-module "^1.0.0" 954 | semver "2 || 3 || 4 || 5" 955 | validate-npm-package-license "^3.0.1" 956 | 957 | object-assign@^4.0.1: 958 | version "4.1.1" 959 | resolved "http://sinopia.app.s/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 960 | 961 | object-keys@^1.0.11, object-keys@^1.0.8: 962 | version "1.0.12" 963 | resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" 964 | 965 | object.assign@^4.1.0: 966 | version "4.1.0" 967 | resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" 968 | dependencies: 969 | define-properties "^1.1.2" 970 | function-bind "^1.1.1" 971 | has-symbols "^1.0.0" 972 | object-keys "^1.0.11" 973 | 974 | object.entries@^1.0.4: 975 | version "1.0.4" 976 | resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" 977 | dependencies: 978 | define-properties "^1.1.2" 979 | es-abstract "^1.6.1" 980 | function-bind "^1.1.0" 981 | has "^1.0.1" 982 | 983 | once@^1.3.0: 984 | version "1.4.0" 985 | resolved "http://sinopia.app.s/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 986 | dependencies: 987 | wrappy "1" 988 | 989 | onetime@^2.0.0: 990 | version "2.0.1" 991 | resolved "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" 992 | dependencies: 993 | mimic-fn "^1.0.0" 994 | 995 | optionator@^0.8.2: 996 | version "0.8.2" 997 | resolved "http://sinopia.app.s/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" 998 | dependencies: 999 | deep-is "~0.1.3" 1000 | fast-levenshtein "~2.0.4" 1001 | levn "~0.3.0" 1002 | prelude-ls "~1.1.2" 1003 | type-check "~0.3.2" 1004 | wordwrap "~1.0.0" 1005 | 1006 | os-tmpdir@~1.0.2: 1007 | version "1.0.2" 1008 | resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 1009 | 1010 | p-limit@^1.1.0: 1011 | version "1.3.0" 1012 | resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" 1013 | dependencies: 1014 | p-try "^1.0.0" 1015 | 1016 | p-locate@^2.0.0: 1017 | version "2.0.0" 1018 | resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" 1019 | dependencies: 1020 | p-limit "^1.1.0" 1021 | 1022 | p-try@^1.0.0: 1023 | version "1.0.0" 1024 | resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" 1025 | 1026 | parse-json@^2.2.0: 1027 | version "2.2.0" 1028 | resolved "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 1029 | dependencies: 1030 | error-ex "^1.2.0" 1031 | 1032 | path-exists@^2.0.0: 1033 | version "2.1.0" 1034 | resolved "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" 1035 | dependencies: 1036 | pinkie-promise "^2.0.0" 1037 | 1038 | path-exists@^3.0.0: 1039 | version "3.0.0" 1040 | resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 1041 | 1042 | path-is-absolute@^1.0.0: 1043 | version "1.0.1" 1044 | resolved "http://sinopia.app.s/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1045 | 1046 | path-is-inside@^1.0.1, path-is-inside@^1.0.2: 1047 | version "1.0.2" 1048 | resolved "http://sinopia.app.s/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 1049 | 1050 | path-key@^2.0.1: 1051 | version "2.0.1" 1052 | resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 1053 | 1054 | path-parse@^1.0.5: 1055 | version "1.0.5" 1056 | resolved "http://sinopia.app.s/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" 1057 | 1058 | path-type@^2.0.0: 1059 | version "2.0.0" 1060 | resolved "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" 1061 | dependencies: 1062 | pify "^2.0.0" 1063 | 1064 | pify@^2.0.0: 1065 | version "2.3.0" 1066 | resolved "http://sinopia.app.s/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 1067 | 1068 | pinkie-promise@^2.0.0: 1069 | version "2.0.1" 1070 | resolved "http://sinopia.app.s/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 1071 | dependencies: 1072 | pinkie "^2.0.0" 1073 | 1074 | pinkie@^2.0.0: 1075 | version "2.0.4" 1076 | resolved "http://sinopia.app.s/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 1077 | 1078 | pkg-dir@^1.0.0: 1079 | version "1.0.0" 1080 | resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" 1081 | dependencies: 1082 | find-up "^1.0.0" 1083 | 1084 | pluralize@^7.0.0: 1085 | version "7.0.0" 1086 | resolved "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" 1087 | 1088 | prelude-ls@~1.1.2: 1089 | version "1.1.2" 1090 | resolved "http://sinopia.app.s/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 1091 | 1092 | prettier@^1.14.0: 1093 | version "1.14.0" 1094 | resolved "https://registry.npmjs.org/prettier/-/prettier-1.14.0.tgz#847c235522035fd988100f1f43cf20a7d24f9372" 1095 | 1096 | progress@^2.0.0: 1097 | version "2.0.0" 1098 | resolved "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" 1099 | 1100 | punycode@^2.1.0: 1101 | version "2.1.1" 1102 | resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 1103 | 1104 | ramda@^0.25.0: 1105 | version "0.25.0" 1106 | resolved "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" 1107 | 1108 | read-pkg-up@^2.0.0: 1109 | version "2.0.0" 1110 | resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" 1111 | dependencies: 1112 | find-up "^2.0.0" 1113 | read-pkg "^2.0.0" 1114 | 1115 | read-pkg@^2.0.0: 1116 | version "2.0.0" 1117 | resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" 1118 | dependencies: 1119 | load-json-file "^2.0.0" 1120 | normalize-package-data "^2.3.2" 1121 | path-type "^2.0.0" 1122 | 1123 | regexp.prototype.flags@^1.2.0: 1124 | version "1.2.0" 1125 | resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" 1126 | dependencies: 1127 | define-properties "^1.1.2" 1128 | 1129 | regexpp@^2.0.0: 1130 | version "2.0.0" 1131 | resolved "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz#b2a7534a85ca1b033bcf5ce9ff8e56d4e0755365" 1132 | 1133 | require-uncached@^1.0.3: 1134 | version "1.0.3" 1135 | resolved "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" 1136 | dependencies: 1137 | caller-path "^0.1.0" 1138 | resolve-from "^1.0.0" 1139 | 1140 | requireindex@~1.1.0: 1141 | version "1.1.0" 1142 | resolved "http://sinopia.app.s/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162" 1143 | 1144 | resolve-from@^1.0.0: 1145 | version "1.0.1" 1146 | resolved "http://sinopia.app.s/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" 1147 | 1148 | resolve@^1.5.0, resolve@^1.6.0: 1149 | version "1.8.1" 1150 | resolved "http://sinopia.app.s/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" 1151 | dependencies: 1152 | path-parse "^1.0.5" 1153 | 1154 | restore-cursor@^2.0.0: 1155 | version "2.0.0" 1156 | resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" 1157 | dependencies: 1158 | onetime "^2.0.0" 1159 | signal-exit "^3.0.2" 1160 | 1161 | rimraf@^2.2.8: 1162 | version "2.6.2" 1163 | resolved "http://sinopia.app.s/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" 1164 | dependencies: 1165 | glob "^7.0.5" 1166 | 1167 | run-async@^2.2.0: 1168 | version "2.3.0" 1169 | resolved "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" 1170 | dependencies: 1171 | is-promise "^2.1.0" 1172 | 1173 | rxjs@^5.5.2: 1174 | version "5.5.11" 1175 | resolved "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87" 1176 | dependencies: 1177 | symbol-observable "1.0.1" 1178 | 1179 | "safer-buffer@>= 2.1.2 < 3": 1180 | version "2.1.2" 1181 | resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1182 | 1183 | "semver@2 || 3 || 4 || 5", semver@^5.5.0: 1184 | version "5.5.0" 1185 | resolved "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" 1186 | 1187 | shebang-command@^1.2.0: 1188 | version "1.2.0" 1189 | resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 1190 | dependencies: 1191 | shebang-regex "^1.0.0" 1192 | 1193 | shebang-regex@^1.0.0: 1194 | version "1.0.0" 1195 | resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 1196 | 1197 | signal-exit@^3.0.2: 1198 | version "3.0.2" 1199 | resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 1200 | 1201 | slice-ansi@1.0.0: 1202 | version "1.0.0" 1203 | resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" 1204 | dependencies: 1205 | is-fullwidth-code-point "^2.0.0" 1206 | 1207 | source-map@^0.5.0: 1208 | version "0.5.7" 1209 | resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1210 | 1211 | spdx-correct@^3.0.0: 1212 | version "3.0.0" 1213 | resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" 1214 | dependencies: 1215 | spdx-expression-parse "^3.0.0" 1216 | spdx-license-ids "^3.0.0" 1217 | 1218 | spdx-exceptions@^2.1.0: 1219 | version "2.1.0" 1220 | resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" 1221 | 1222 | spdx-expression-parse@^3.0.0: 1223 | version "3.0.0" 1224 | resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 1225 | dependencies: 1226 | spdx-exceptions "^2.1.0" 1227 | spdx-license-ids "^3.0.0" 1228 | 1229 | spdx-license-ids@^3.0.0: 1230 | version "3.0.0" 1231 | resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" 1232 | 1233 | sprintf-js@~1.0.2: 1234 | version "1.0.3" 1235 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1236 | 1237 | string-width@^2.1.0, string-width@^2.1.1: 1238 | version "2.1.1" 1239 | resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 1240 | dependencies: 1241 | is-fullwidth-code-point "^2.0.0" 1242 | strip-ansi "^4.0.0" 1243 | 1244 | string.prototype.matchall@^2.0.0: 1245 | version "2.0.0" 1246 | resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz#2af8fe3d2d6dc53ca2a59bd376b089c3c152b3c8" 1247 | dependencies: 1248 | define-properties "^1.1.2" 1249 | es-abstract "^1.10.0" 1250 | function-bind "^1.1.1" 1251 | has-symbols "^1.0.0" 1252 | regexp.prototype.flags "^1.2.0" 1253 | 1254 | strip-ansi@^3.0.0: 1255 | version "3.0.1" 1256 | resolved "http://sinopia.app.s/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1257 | dependencies: 1258 | ansi-regex "^2.0.0" 1259 | 1260 | strip-ansi@^4.0.0: 1261 | version "4.0.0" 1262 | resolved "http://sinopia.app.s/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 1263 | dependencies: 1264 | ansi-regex "^3.0.0" 1265 | 1266 | strip-bom@^3.0.0: 1267 | version "3.0.0" 1268 | resolved "http://sinopia.app.s/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 1269 | 1270 | strip-json-comments@^2.0.1: 1271 | version "2.0.1" 1272 | resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1273 | 1274 | supports-color@3.1.2: 1275 | version "3.1.2" 1276 | resolved "http://sinopia.app.s/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" 1277 | dependencies: 1278 | has-flag "^1.0.0" 1279 | 1280 | supports-color@^2.0.0: 1281 | version "2.0.0" 1282 | resolved "http://sinopia.app.s/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1283 | 1284 | supports-color@^5.3.0: 1285 | version "5.4.0" 1286 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" 1287 | dependencies: 1288 | has-flag "^3.0.0" 1289 | 1290 | symbol-observable@1.0.1: 1291 | version "1.0.1" 1292 | resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" 1293 | 1294 | table@^4.0.3: 1295 | version "4.0.3" 1296 | resolved "https://registry.npmjs.org/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" 1297 | dependencies: 1298 | ajv "^6.0.1" 1299 | ajv-keywords "^3.0.0" 1300 | chalk "^2.1.0" 1301 | lodash "^4.17.4" 1302 | slice-ansi "1.0.0" 1303 | string-width "^2.1.1" 1304 | 1305 | text-table@^0.2.0: 1306 | version "0.2.0" 1307 | resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 1308 | 1309 | through@^2.3.6: 1310 | version "2.3.8" 1311 | resolved "http://sinopia.app.s/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1312 | 1313 | tmp@^0.0.33: 1314 | version "0.0.33" 1315 | resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" 1316 | dependencies: 1317 | os-tmpdir "~1.0.2" 1318 | 1319 | to-fast-properties@^2.0.0: 1320 | version "2.0.0" 1321 | resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" 1322 | 1323 | trim-right@^1.0.1: 1324 | version "1.0.1" 1325 | resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" 1326 | 1327 | type-check@~0.3.2: 1328 | version "0.3.2" 1329 | resolved "http://sinopia.app.s/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 1330 | dependencies: 1331 | prelude-ls "~1.1.2" 1332 | 1333 | uri-js@^4.2.1: 1334 | version "4.2.2" 1335 | resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 1336 | dependencies: 1337 | punycode "^2.1.0" 1338 | 1339 | validate-npm-package-license@^3.0.1: 1340 | version "3.0.3" 1341 | resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" 1342 | dependencies: 1343 | spdx-correct "^3.0.0" 1344 | spdx-expression-parse "^3.0.0" 1345 | 1346 | which@^1.2.9: 1347 | version "1.3.1" 1348 | resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1349 | dependencies: 1350 | isexe "^2.0.0" 1351 | 1352 | wordwrap@~1.0.0: 1353 | version "1.0.0" 1354 | resolved "http://sinopia.app.s/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 1355 | 1356 | wrappy@1: 1357 | version "1.0.2" 1358 | resolved "http://sinopia.app.s/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1359 | 1360 | write@^0.2.1: 1361 | version "0.2.1" 1362 | resolved "http://sinopia.app.s/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" 1363 | dependencies: 1364 | mkdirp "^0.5.1" 1365 | --------------------------------------------------------------------------------