├── .gitignore ├── .jshintignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── LICENSE ├── README.md ├── index.js ├── package.json ├── release-notes.yml ├── test ├── .jshintrc ├── _utils.js ├── configuration.js ├── indexes.js ├── integration.js ├── middleware.js ├── opt-out.js ├── plugin.js └── require-tenant-id.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .idea 5 | 6 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 6, 3 | "node": true, 4 | "laxbreak": true 5 | } 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .travis.yml 2 | coverage 3 | test 4 | .nyc_output 5 | .idea 6 | .jshint 7 | .jshintignore 8 | CODE_OF_CONDUCT.md 9 | CONTRIBUTING.md 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "14" 4 | - "12" 5 | - "10" 6 | - "8" 7 | - "6" 8 | env: 9 | - MONGOOSE_VERSION=5 10 | - MONGOOSE_VERSION=4 11 | services: mongodb 12 | cache: yarn 13 | git: 14 | depth: 3 15 | before_script: 16 | - sleep 15 17 | install: 18 | - yarn 19 | - yarn add --dev mongoose@^$MONGOOSE_VERSION 20 | script: 21 | - yarn hint 22 | - yarn test-and-cover 23 | jobs: 24 | include: 25 | - stage: deploy 26 | if: env(MONGOOSE_VERSION) = 5 27 | node_js: "14" 28 | script: 29 | - yarn test-and-cover 30 | - yarn coveralls 31 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alrik.zachert@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to node-mongo-tenant 2 | 3 | :sparkles::tada: Many thanks for contributing! :tada::sparkles: 4 | 5 | ## First of all 6 | 7 | Any contribution is welcome. 8 | This project is committed to the following [CODE OF CONDUCT](CODE_OF_CONDUCT.md). 9 | 10 | ## How can I contribute? 11 | 12 | * Write some docs or tutorial 13 | * Start a discussion about a new feature 14 | * Report a bug 15 | * Submit a PR 16 | * Open an issue to give feedback 17 | * Write tests 18 | * Suggest updates to this document 19 | * ... 20 | 21 | ## Contribution Guidelines 22 | 23 | * :+1: This project follows [git flow](http://nvie.com/posts/a-successful-git-branching-model/) 24 | * :+1: Releases are [semanticly versioned](http://semver.org/) 25 | * :+1: Code coverage should remain 100% 26 | * :+1: Changes should be stated in `release-notes.yml` 27 | 28 | ### Creating a feature branch 29 | 30 | For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), 31 | issue the pull request against the "develop" branch. 32 | 33 | ```sh 34 | $ git checkout develop 35 | $ git fetch origin 36 | $ git rebase origin/develop 37 | $ git checkout -b feature/${ISSUE_NUMBER} 38 | ``` 39 | 40 | * Write the changes to `release-notes.yml` underneath `version: Unreleased` 41 | 42 | ### Creating a hotfix branch 43 | 44 | For hotfixes against the stable release, issue the pull request against the "master" branch. 45 | 46 | 47 | ```sh 48 | $ git checkout master 49 | $ git fetch origin 50 | $ git rebase origin/master 51 | $ git checkout -b hotfix/${ISSUE_NUMBER} 52 | ``` 53 | 54 | * Bump the version in `package.json` to the next patch level (`"1.1.0" => "1.1.1"`). 55 | * State the new version's changes to `release-notes.yml` 56 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | Many thanks for contributing to [node-mongo-tenant](https://github.com/craftup/node-mongo-tenant) 4 | 5 | * [baranga](https://github.com/baranga) 6 | * [ivanseidel](https://github.com/ivanseidel) 7 | * [felipe-augusto](https://github.com/felipe-augusto) 8 | 9 | A full list of contributors can be viewed [here](https://github.com/craftup/node-mongo-tenant/graphs/contributors). 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2019 RealMQ GmbH 4 | Copyright (c) 2016-2018 Alrik Zachert & Henning Panke 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Multi Tenancy Plugin for Mongoose 2 | 3 | [![Subscribe to Release Notes](https://release-notes.com/badges/v1.svg)](https://release-notes.com/@craftup/node-mongo-tenant) 4 | [![Get Help on Gitter](https://img.shields.io/gitter/room/RealMQ/node-mongo-tenant.svg)](https://gitter.im/RealMQ/node-mongo-tenant) 5 | [![Build Status](https://travis-ci.org/craftup/node-mongo-tenant.png?branch=master)](https://travis-ci.org/craftup/node-mongo-tenant) 6 | [![Coverage Status](https://coveralls.io/repos/github/craftup/node-mongo-tenant/badge.svg?branch=master)](https://coveralls.io/github/craftup/node-mongo-tenant?branch=master) 7 | [![npm version](https://badge.fury.io/js/mongo-tenant.svg)](https://badge.fury.io/js/mongo-tenant) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/craftup/node-mongo-tenant/master/LICENSE) 9 | 10 | ## Prelude 11 | 12 | There are 3 ways of implementing multi-tenancy in mongoDB: 13 | 14 | - on document level (cheap and easy to administer but only secured by app logic) 15 | - on collection level (not recommended, due to breaking mongoDB concepts) 16 | - on database level (very flexible and secure but expensive) 17 | 18 | ## About 19 | 20 | The mongo tenant is a highly configurable mongoose plugin solving multi-tenancy problems on 21 | document level (for now...). 22 | It creates a tenant-reference field and takes care of unique indexes. 23 | Also it provides access to tenant-bound model-classes, that prohibit the 24 | exploid of the given tenant scope. 25 | Last but not least the "MAGIC" can be disabled so that shipping of the 26 | same code in single- and multi-tenancy environment (on premis vs. cloud hosted) 27 | is a question of a single line of config. 28 | 29 | ## Requirements 30 | 31 | Mongo tenant is compatible with mongoose 4 and 5. 32 | 33 | ## Incompatibilities 34 | 35 | * Mongo Tenant does not work with mongoose 4.8.1-4.8.2 see [Automattic/mongoose#4947](https://github.com/Automattic/mongoose/issues/4947). 36 | 37 | ## Install 38 | 39 | ```sh 40 | $ npm i -S mongo-tenant 41 | // or 42 | $ yarn add mongo-tenant 43 | ``` 44 | 45 | ## Use 46 | 47 | Register the plugin on the relevant mongoose schema. 48 | 49 | ```javascript 50 | const mongoose = require('mongoose'); 51 | const mongoTenant = require('mongo-tenant'); 52 | 53 | const MySchema = new mongoose.Schema({}); 54 | MySchema.plugin(mongoTenant); 55 | 56 | const MyModel = mongoose.model('MyModel', MySchema); 57 | ``` 58 | 59 | Retrieve the model in tenant scope with static `byTenant` method. This will return 60 | a new model subclass that has special tenant-scope guards. 61 | It has the exactly same interface as any other mongoose model but prevents 62 | the access to other tenant scopes. 63 | 64 | ```javascript 65 | const MyTenantBoundModel = MyModel.byTenant('some-tenant-id'); 66 | 67 | (new MyTenantBoundModel()).getTenantId() === 'some-tenant-id'; // true 68 | 69 | // silently ignore other tenant scope 70 | (new MyTenantBoundModel({ 71 | tenantId: 'some-other-tenant-id' 72 | })).getTenantId() === 'some-tenant-id'; // true 73 | 74 | ``` 75 | 76 | You can check for tenant context of a model class or instance by checking 77 | the `hasTenantContext` property. If this is truthy you may want to retrieve 78 | the bound tenant scope with `getTenantId()` method. 79 | 80 | ```javascript 81 | 82 | // With enabled mongo-tenant on a schema, all tenant bound models 83 | // and there instances provide the hasTenantContext flag 84 | if (SomeModelClassOrInstance.hasTenantContext) { 85 | const tenantId = SomeModelClassOrInstance.getTenantId(); 86 | ... 87 | } 88 | ``` 89 | 90 | ### Indexes 91 | 92 | The mongo-tenant takes care of the tenant-reference field, so that you 93 | will be able to use your existing schema definitions and just plugin the 94 | mongo-tenant without changing a single line of schema definition. 95 | 96 | But under the hood the mongo-tenant creates an indexed field *(tenantId by default)* 97 | and includes this in all defined unique indexes. So by default, all unique 98 | fields (and compound indexes) are unique for a single tenant id. 99 | 100 | You may have use-cases where you want to archive global uniqueness. 101 | To skip the automatic unique key extension of mongo-tenant for a specific 102 | index you can set the `preserveUniqueKey` config option to true. 103 | 104 | ```javascript 105 | const MySchema = new mongoose.Schema({ 106 | someField: { 107 | unique: true, 108 | preserveUniqueKey: true 109 | }, 110 | anotherField: String, 111 | yetAnotherField: String 112 | }); 113 | 114 | MySchema.index({ 115 | anotherField: 1, 116 | yetAnotherField: 1 117 | }, { 118 | unique: true, 119 | preserveUniqueKey: true 120 | }); 121 | ``` 122 | 123 | ### Context bound models and populate 124 | 125 | Once a model with tenant context is created it will try to keep the context 126 | for other models created via it. Whenever it detects that a subsequent models 127 | tenant configuration is compatible to its own, it will return that model 128 | bound to the same tenant context. 129 | 130 | ```javascript 131 | const AuthorSchema = new mongoose.Schema({}); 132 | AuthorSchema.plugin(mongoTenant); 133 | const AuthorModel = mongoose.model('author', AuthorSchema); 134 | 135 | const BookSchema = new mongoose.Schema({ 136 | author: { type: mongoose.Schema.Types.ObjectId, ref: 'author' } 137 | }); 138 | BookSchema.plugin(mongoTenant); 139 | const BookModel = mongoose.model('book', BookSchema); 140 | 141 | const BoundBookModel = BookModel.byTenant('some-tenant-id'); 142 | BoundBookModel.model('author'); // return author model bound to "some-tenant-id" 143 | BoundBookModel.db.model('author'); // return author model bound to "some-tenant-id" 144 | ``` 145 | 146 | ### Configuration 147 | 148 | The mongo tenant works out of the box, so all config options are optional. 149 | But you have the ability to adjust the behavior and api of the mongo tenant 150 | to your needs. 151 | 152 | ```javascript 153 | const config = { 154 | /** 155 | * Whether the mongo tenant plugin MAGIC is enabled. Default: true 156 | */ 157 | enabled: false, 158 | 159 | /** 160 | * The name of the tenant id field. Default: tenantId 161 | */ 162 | tenantIdKey: 'customerId', 163 | 164 | /** 165 | * The type of the tenant id field. Default: String 166 | */ 167 | tenantIdType: Number, 168 | 169 | /** 170 | * The name of the tenant id getter method. Default: getTenantId 171 | */ 172 | tenantIdGetter: 'getCustomerId', 173 | 174 | /** 175 | * The name of the tenant bound model getter method. Default: byTenant 176 | */ 177 | accessorMethod: 'byCustomer', 178 | 179 | /** 180 | * Enforce tenantId field to be set. Default: false 181 | * NOTE: this option will become enabled by default in mongo-tenant@2.0 182 | */ 183 | requireTenantId: true 184 | }; 185 | 186 | SomeSchema.plugin(mongoTenant, config); 187 | ``` 188 | 189 | ### Running Tests 190 | 191 | Some tests rely on a running mongoDB and by default the tests are performed 192 | against 'mongodb://localhost/mongo-tenant-test'. 193 | The tests can also be run against a custom mongoDB by passing the 194 | custom connection string to **MONGO_URI** environment variable. 195 | 196 | ```sh 197 | # perform jshint on sources and tests 198 | $ npm run hint 199 | 200 | # run the tests and gather coverage report 201 | $ npm run test-and-cover 202 | 203 | # run tests with custom mongoDB uri 204 | $ MONGO_URI='mongodb://user:password@xyz.mlab.com:23315/mongo-tenant-test' npm run test-and-cover 205 | ``` 206 | 207 | ### LICENSE 208 | 209 | The files in this archive are released under MIT license. 210 | You can find a copy of this license in [LICENSE](https://github.com/craftup/node-mongo-tenant/raw/master/LICENSE). 211 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | /** 11 | * MongoTenant is a class aimed for use in mongoose schema plugin scope. 12 | * It adds support for multi-tenancy on document level (adding a tenant reference field and include this in unique indexes). 13 | * Furthermore it provides an API for tenant bound models. 14 | * 15 | * @property {object} _modelCache 16 | * @property {object} schema 17 | */ 18 | class MongoTenant { 19 | /** 20 | * Create a new mongo tenant from a given schema. 21 | * 22 | * @param {Object} [options] - A hash of configuration options. 23 | * @param {boolean} [options.enabled] - Whether the mongo tenant plugin is enabled. Default: **true**. 24 | * @param {string} [options.tenantIdKey] - The name of the tenant id field. Default: **tenantId**. 25 | * @param {string|*} [options.tenantIdType] - The type of the tenant id field. Default: **String**. 26 | * @param {string} [options.tenantIdGetter] - The name of the tenant id getter method. Default: **getTenantId**. 27 | * @param {string} [options.accessorMethod] - The name of the tenant bound model getter method. Default: **byTenant**. 28 | * @param {boolean} [options.requireTenantId] - Whether tenant id field should be required. Default: **false**. 29 | */ 30 | constructor(schema, options) { 31 | this.options = options || {}; 32 | 33 | const modelCache = {}; 34 | Object.defineProperties(this, { 35 | _modelCache: { 36 | get: () => modelCache, 37 | }, 38 | schema: { 39 | get: () => schema, 40 | } 41 | }); 42 | } 43 | 44 | /** 45 | * Apply the mongo tenant plugin to the given schema. 46 | * 47 | * @returns {MongoTenant} 48 | */ 49 | apply() { 50 | this 51 | .extendSchema() 52 | .compoundIndexes() 53 | .injectApi() 54 | .installMiddleWare(); 55 | } 56 | 57 | /** 58 | * Returns the boolean flag whether the mongo tenant is enabled. 59 | * 60 | * @returns {boolean} 61 | */ 62 | isEnabled() { 63 | return !!(typeof this.options.enabled === "undefined" ? true : this.options.enabled); 64 | } 65 | 66 | /** 67 | * Return the name of the tenant id field. Defaults to **tenantId**. 68 | * 69 | * @returns {string} 70 | */ 71 | getTenantIdKey() { 72 | return this.options.tenantIdKey || 'tenantId'; 73 | } 74 | 75 | /** 76 | * Return the type of the tenant id field. Defaults to **String**. 77 | * 78 | * @returns {*|String} 79 | */ 80 | getTenantIdType() { 81 | return this.options.tenantIdType || String; 82 | } 83 | 84 | /** 85 | * Return the method name for accessing tenant-bound models. 86 | * 87 | * @returns {*|string} 88 | */ 89 | getAccessorMethod() { 90 | return this.options.accessorMethod || 'byTenant'; 91 | } 92 | 93 | /** 94 | * Return the name of the tenant id getter method. 95 | * 96 | * @returns {*|string} 97 | */ 98 | getTenantIdGetter() { 99 | return this.options.tenantIdGetter || 'getTenantId'; 100 | } 101 | 102 | /** 103 | * Check if tenant id is a required field. 104 | * 105 | * @return {boolean} 106 | */ 107 | isTenantIdRequired() { 108 | return this.options.requireTenantId === true; 109 | } 110 | 111 | /** 112 | * Checks if instance is compatible to other plugin instance 113 | * 114 | * For population of referenced models it's necessary to detect if the tenant 115 | * plugin installed in these models is compatible to the plugin of the host 116 | * model. If they are compatible they are one the same "level". 117 | * 118 | * @param {MongoTenant} plugin 119 | */ 120 | isCompatibleTo(plugin) { 121 | return ( 122 | plugin && 123 | typeof plugin.getAccessorMethod === 'function' && 124 | typeof plugin.getTenantIdKey === 'function' && 125 | this.getTenantIdKey() === plugin.getTenantIdKey() 126 | ); 127 | } 128 | 129 | /** 130 | * Inject tenantId field into schema definition. 131 | * 132 | * @returns {MongoTenant} 133 | */ 134 | extendSchema() { 135 | if (this.isEnabled()) { 136 | let tenantField = { 137 | [this.getTenantIdKey()]: { 138 | index: true, 139 | type: this.getTenantIdType(), 140 | required: this.isTenantIdRequired(), 141 | } 142 | }; 143 | 144 | this.schema.add(tenantField); 145 | } 146 | 147 | return this; 148 | } 149 | 150 | /** 151 | * Consider the tenant id field in all unique indexes (schema- and field level). 152 | * Take the optional **preserveUniqueKey** option into account for oupting out the default behaviour. 153 | * 154 | * @returns {MongoTenant} 155 | */ 156 | compoundIndexes() { 157 | if (this.isEnabled()) { 158 | // apply tenancy awareness to schema level unique indexes 159 | this.schema._indexes.forEach((index) => { 160 | // extend uniqueness of indexes by tenant id field 161 | // skip if perserveUniqueKey of the index is set to true 162 | if (index[1].unique === true && index[1].preserveUniqueKey !== true) { 163 | let tenantAwareIndex = { 164 | [this.getTenantIdKey()]: 1 165 | }; 166 | 167 | for (let indexedField in index[0]) { 168 | tenantAwareIndex[indexedField] = index[0][indexedField]; 169 | } 170 | 171 | index[0] = tenantAwareIndex; 172 | } 173 | }); 174 | 175 | // apply tenancy awareness to field level unique indexes 176 | this.schema.eachPath((key, path) => { 177 | let pathOptions = path.options; 178 | 179 | // skip if perserveUniqueKey of an unique field is set to true 180 | if (pathOptions.unique === true && pathOptions.preserveUniqueKey !== true) { 181 | // delete the old index 182 | path._index = null; 183 | delete path.options.unique; 184 | 185 | // prepare new options 186 | let indexOptions = { 187 | unique: true 188 | }; 189 | 190 | // add sparse option if set in options 191 | if (pathOptions.sparse) { 192 | indexOptions.sparse = true; 193 | } 194 | 195 | // add partialFilterExpression option if set in options 196 | if (pathOptions.partialFilterExpression) { 197 | indexOptions.partialFilterExpression = pathOptions.partialFilterExpression; 198 | } 199 | 200 | // create a new one that includes the tenant id field 201 | this.schema.index({ 202 | [this.getTenantIdKey()]: 1, 203 | [key]: 1 204 | }, indexOptions); 205 | } 206 | }); 207 | } 208 | 209 | return this; 210 | } 211 | 212 | /** 213 | * Inject the user-space entry point for mongo tenant. 214 | * This method adds a static Model method to retrieve tenant bound sub-classes. 215 | * 216 | * @returns {MongoTenant} 217 | */ 218 | injectApi() { 219 | let me = this; 220 | 221 | Object.assign(this.schema.statics, { 222 | [this.getAccessorMethod()]: function (tenantId) { 223 | if (!me.isEnabled()) { 224 | return this.model(this.modelName); 225 | } 226 | 227 | let modelCache = me._modelCache[this.modelName] || (me._modelCache[this.modelName] = {}); 228 | 229 | // lookup tenant-bound model in cache 230 | if (!modelCache[tenantId]) { 231 | let Model = this.model(this.modelName); 232 | 233 | // Cache the tenant bound model class. 234 | modelCache[tenantId] = me.createTenantAwareModel(Model, tenantId); 235 | } 236 | 237 | return modelCache[tenantId]; 238 | }, 239 | 240 | get mongoTenant() { 241 | return me; 242 | } 243 | }); 244 | 245 | return this; 246 | } 247 | 248 | /** 249 | * Create a model class that is bound the given tenant. 250 | * So that all operations on this model prohibit leaving the tenant scope. 251 | * 252 | * @param BaseModel 253 | * @param tenantId 254 | * @returns {MongoTenantModel} 255 | */ 256 | createTenantAwareModel(BaseModel, tenantId) { 257 | let 258 | tenantIdGetter = this.getTenantIdGetter(), 259 | tenantIdKey = this.getTenantIdKey(); 260 | 261 | const db = this.createTenantAwareDb(BaseModel.db, tenantId); 262 | 263 | class MongoTenantModel extends BaseModel { 264 | static get hasTenantContext() { 265 | return true; 266 | } 267 | 268 | static [tenantIdGetter]() { 269 | return tenantId; 270 | } 271 | 272 | /** 273 | * @see Mongoose.Model.aggregate 274 | * @param {...Object|Array} [operations] aggregation pipeline operator(s) or operator array 275 | * @param {Function} [callback] 276 | * @return {Mongoose.Aggregate|Promise} 277 | */ 278 | static aggregate() { 279 | let operations = Array.prototype.slice.call(arguments); 280 | let pipeline = operations; 281 | 282 | if (Array.isArray(operations[0])) { 283 | pipeline = operations[0]; 284 | } else if (arguments.length === 1 || typeof arguments[1] === 'function') { 285 | // mongoose 5.x compatibility 286 | pipeline = operations[0] = [operations[0]]; 287 | } 288 | 289 | pipeline.unshift({ 290 | $match: { 291 | [tenantIdKey]: this[tenantIdGetter]() 292 | } 293 | }); 294 | 295 | return super.aggregate.apply(this, operations); 296 | } 297 | 298 | static deleteOne(conditions, callback) { 299 | conditions[tenantIdKey] = this[tenantIdGetter](); 300 | 301 | return super.deleteOne(conditions, callback); 302 | } 303 | 304 | static deleteMany(conditions, options, callback) { 305 | conditions[tenantIdKey] = this[tenantIdGetter](); 306 | 307 | return super.deleteMany(conditions, options, callback); 308 | } 309 | 310 | static remove(conditions, callback) { 311 | if (arguments.length === 1 && typeof conditions === 'function') { 312 | callback = conditions; 313 | conditions = {}; 314 | } 315 | 316 | conditions[tenantIdKey] = this[tenantIdGetter](); 317 | 318 | return super.remove(conditions, callback); 319 | } 320 | 321 | static insertMany(docs, callback) { 322 | let 323 | me = this, 324 | tenantId = this[tenantIdGetter](); 325 | 326 | // Model.inserMany supports a single document as parameter 327 | if (!Array.isArray(docs)) { 328 | docs[tenantIdKey] = tenantId; 329 | } else { 330 | docs.forEach(function (doc, key) { 331 | doc[tenantIdKey] = tenantId; 332 | }); 333 | } 334 | 335 | // ensure the returned docs are instanced of the bould multi tenant model 336 | return super.insertMany(docs, (err, docs) => { 337 | if (err) { 338 | return callback && callback(err); 339 | } 340 | 341 | return callback && callback(null, docs.map(doc => new me(doc))); 342 | }); 343 | } 344 | 345 | static get db() { 346 | return db; 347 | } 348 | 349 | get hasTenantContext() { 350 | return true; 351 | } 352 | 353 | [tenantIdGetter]() { 354 | return tenantId; 355 | } 356 | } 357 | 358 | // inherit all static properties from the mongoose base model 359 | for (let staticProperty of Object.getOwnPropertyNames(BaseModel)) { 360 | if (MongoTenantModel.hasOwnProperty(staticProperty) 361 | || ['arguments', 'caller'].indexOf(staticProperty) !== -1 362 | ) { 363 | continue; 364 | } 365 | 366 | let descriptor = Object.getOwnPropertyDescriptor(BaseModel, staticProperty); 367 | Object.defineProperty(MongoTenantModel, staticProperty, descriptor); 368 | } 369 | 370 | // create tenant models for discriminators if they exist 371 | if (BaseModel.discriminators) { 372 | MongoTenantModel.discriminators = {}; 373 | 374 | for (let key in BaseModel.discriminators) { 375 | MongoTenantModel.discriminators[key] = this.createTenantAwareModel(BaseModel.discriminators[key], tenantId); 376 | } 377 | } 378 | 379 | return MongoTenantModel; 380 | } 381 | 382 | /** 383 | * Create db connection bound to a specific tenant 384 | * 385 | * @param {Connection} unawareDb 386 | * @param {*} tenantId 387 | * @returns {Connection} 388 | */ 389 | createTenantAwareDb(unawareDb, tenantId) { 390 | const me = this; 391 | const awareDb = Object.create(unawareDb); 392 | awareDb.model = (name) => { 393 | const unawareModel = unawareDb.model(name); 394 | const otherPlugin = unawareModel.mongoTenant; 395 | 396 | if (!me.isCompatibleTo(otherPlugin)) { 397 | return unawareModel; 398 | } 399 | 400 | return unawareModel[otherPlugin.getAccessorMethod()](tenantId); 401 | }; 402 | return awareDb; 403 | } 404 | 405 | /** 406 | * Install schema middleware to guard the tenant context of models. 407 | * 408 | * @returns {MongoTenant} 409 | */ 410 | installMiddleWare() { 411 | let 412 | me = this, 413 | tenantIdGetter = this.getTenantIdGetter(), 414 | tenantIdKey = this.getTenantIdKey(); 415 | 416 | this.schema.pre('count', function(next) { 417 | if (this.model.hasTenantContext) { 418 | this._conditions[tenantIdKey] = this.model[tenantIdGetter](); 419 | } 420 | 421 | next(); 422 | }); 423 | 424 | this.schema.pre('find', function(next) { 425 | if (this.model.hasTenantContext) { 426 | this._conditions[tenantIdKey] = this.model[tenantIdGetter](); 427 | } 428 | 429 | next(); 430 | }); 431 | 432 | 433 | this.schema.pre('countDocuments', function(next) { 434 | if (this.model.hasTenantContext) { 435 | this._conditions[tenantIdKey] = this.model[tenantIdGetter](); 436 | } 437 | 438 | next(); 439 | }); 440 | 441 | this.schema.pre('findOne', function(next) { 442 | if (this.model.hasTenantContext) { 443 | this._conditions[tenantIdKey] = this.model[tenantIdGetter](); 444 | } 445 | 446 | next(); 447 | }); 448 | 449 | this.schema.pre('findOneAndRemove', function(next) { 450 | if (this.model.hasTenantContext) { 451 | this._conditions[tenantIdKey] = this.model[tenantIdGetter](); 452 | } 453 | 454 | next(); 455 | }); 456 | 457 | this.schema.pre('findOneAndUpdate', function(next) { 458 | if (this.model.hasTenantContext) { 459 | me._guardUpdateQuery(this); 460 | } 461 | 462 | next(); 463 | }); 464 | 465 | this.schema.pre('save', function(next) { 466 | if (this.constructor.hasTenantContext) { 467 | this[tenantIdKey] = this.constructor[tenantIdGetter](); 468 | } 469 | 470 | next(); 471 | }); 472 | 473 | this.schema.pre('update', function(next) { 474 | if (this.model.hasTenantContext) { 475 | me._guardUpdateQuery(this); 476 | } 477 | 478 | next(); 479 | }); 480 | 481 | this.schema.pre('updateMany', function(next) { 482 | if (this.model.hasTenantContext) { 483 | me._guardUpdateQuery(this); 484 | } 485 | 486 | next(); 487 | }); 488 | 489 | return this; 490 | } 491 | 492 | /** 493 | * Avoid breaking tenant context from update operations. 494 | * 495 | * @param {mongoose.Query} query 496 | * @private 497 | */ 498 | _guardUpdateQuery(query) { 499 | let 500 | tenantIdGetter = this.getTenantIdGetter(), 501 | tenantIdKey = this.getTenantIdKey(), 502 | tenantId = query.model[tenantIdGetter](), 503 | $set = query._update.$set; 504 | 505 | query._conditions[tenantIdKey] = tenantId; 506 | 507 | // avoid jumping tenant context when overwriting a model. 508 | if ((tenantIdKey in query._update) || query.options.overwrite) { 509 | query._update[tenantIdKey] = tenantId; 510 | } 511 | 512 | // avoid jumping tenant context from $set operations 513 | if ($set && (tenantIdKey in $set) && $set[tenantIdKey] !== tenantId) { 514 | $set[tenantIdKey] = tenantId; 515 | } 516 | } 517 | } 518 | 519 | /** 520 | * The mongo tenant mongoose plugin. 521 | * 522 | * @param {mongoose.Schema} schema 523 | * @param {Object} options 524 | */ 525 | function mongoTenantPlugin(schema, options) { 526 | let mongoTenant = new MongoTenant(schema, options); 527 | 528 | mongoTenant.apply(); 529 | } 530 | 531 | mongoTenantPlugin.MongoTenant = MongoTenant; 532 | 533 | module.exports = mongoTenantPlugin; 534 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongo-tenant", 3 | "version": "1.8.0", 4 | "description": "The mongo-tenant is a multi-tenancy plugin for mongoose.", 5 | "author": "RealMQ GmbH ", 6 | "contributors": [ 7 | "Alrik Zachert ", 8 | "Henning Panke " 9 | ], 10 | "keywords": [ 11 | "multi-tenancy", 12 | "multitenancy", 13 | "multi-tenant", 14 | "multitenant", 15 | "mongoose", 16 | "mongodb", 17 | "mongo" 18 | ], 19 | "scripts": { 20 | "hint": "jshint .", 21 | "test": "mocha --exit", 22 | "test-and-cover": "nyc --reporter=html --reporter=text npm run test", 23 | "coveralls": "nyc report --reporter=text-lcov | coveralls", 24 | "validate-release-notes": "release-notes validate" 25 | }, 26 | "main": "index.js", 27 | "bugs": { 28 | "url": "https://github.com/craftup/node-mongo-tenant/issues" 29 | }, 30 | "repository": { 31 | "url": "https://github.com/craftup/node-mongo-tenant" 32 | }, 33 | "license": "MIT", 34 | "devDependencies": { 35 | "@release-notes/cli": "^0.3.0", 36 | "chai": "^4.2.0", 37 | "coveralls": "^3.1.0", 38 | "jshint": "^2.11.1", 39 | "mocha": "^5.2.0", 40 | "mocha-mongoose": "^1.2.0", 41 | "mongodb": "^2.2.36", 42 | "mongoose": "^5.9.23", 43 | "nyc": "^11.9.0" 44 | }, 45 | "peerDependencies": { 46 | "mongoose": ">=4.3.0 <=4.8.0 || >=4.8.3" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /release-notes.yml: -------------------------------------------------------------------------------- 1 | title: Release Notes of node-mongo-tenant 2 | description: > 3 | The mongo tenant is a highly configurable mongoose plugin solving multi-tenancy problems on 4 | document level (for now...). It creates a tenant-reference field and takes care of unique indexes. 5 | Also it provides access to tenant-bound model-classes, that prohibit the exploid of the given tenant scope. 6 | Last but not least the "MAGIC" can be disabled so that shipping of the same code in single- and 7 | multi-tenancy environment (on premis vs. cloud hosted) is a question of a single line of config. 8 | 9 | releases: 10 | - version: 1.8.0 11 | date: 2020-07-12 12 | fixed: 13 | - Missing tenant context in updateMany ([#61](https://github.com/craftup/node-mongo-tenant/issues/61)). 14 | - Audit and update dev dependencies 15 | - Exclude unnecessary files from npm package. 16 | added: 17 | - Extend offical node support to 10, 12 and 14 LTS releases. 18 | - version: 1.7.0 19 | date: 2019-08-02 20 | fixed: 21 | - Missing tenant context in countDocuments ([#45](https://github.com/craftup/node-mongo-tenant/issues/45)). 22 | - Audit and update dependencies, fixing 52 vulnerabilities. 23 | - version: 1.6.0 24 | date: 2019-03-21 25 | fixed: 26 | - Missing tenant context in populated subdocuments ([#16](https://github.com/craftup/node-mongo-tenant/issues/16)). 27 | changed: 28 | - Models with tenant context (`Model.byTenant(...)`) will have a modified db connection object 29 | returning Models bound to same context. 30 | - Public schema reference of plugin instances became unenumerable. 31 | This is necessary to avoid inifinite loops in case two tenant aware schemas are used in a discriminator setup. 32 | - version: 1.5.0 33 | date: 2018-07-06 34 | fixed: 35 | - Fix discriminator handling, properly preserve tenant scope. ([#38](https://github.com/craftup/node-mongo-tenant/issues/38)) 36 | - version: 1.4.0 37 | date: 2018-03-20 38 | description: Mongoose 5 compatibility 39 | added: 40 | - > 41 | Make mongo tenant compatible with mongoose 5. :tada: ([#34](https://github.com/craftup/node-mongo-tenant/issues/34)) 42 | - version: 1.3.2 43 | date: 2017-11-10 44 | fixed: 45 | - title: Fix coveralls / travis-ci integration. 46 | tags: ['Tests'] 47 | - version: 1.3.1 48 | date: 2017-11-10 49 | improved: 50 | - title: Generate coverage reports with `nyc` instead of `istanbul`. 51 | tags: ['Tests'] 52 | fixed: 53 | - title: Fix test system to exit after the last test. 54 | tags: ['Tests'] 55 | - version: 1.3.0 56 | date: 2017-11-07 57 | added: 58 | - Introduce this release notes definition. (#23) 59 | - Add config option `requireTenantId` in order to enforce tenant id to be set. (#28) 60 | - version: 1.2.0 61 | date: 2017-08-28 62 | added: 63 | - Add support for sparse option in unique fields. (#20) 64 | - Add partialFilterExpression as option to indexes. (#21) 65 | - version: 1.1.0 66 | date: 2017-08-21 67 | added: 68 | - Add support for aggregation pipeline argument passed as array. (#14) 69 | improved: 70 | - Use native promise to avoid the mongoose deprecation warning. 71 | - Fix mongoose initialization deprecation warning by using mongoClient. 72 | - version: 1.0.4 73 | date: 2017-02-06 74 | improved: 75 | - Improve compatibility to latest mongoose version. 76 | - version: 1.0.3 77 | date: 2017-02-06 78 | fixed: 79 | - Upgrade testrunner mocha to version 3. 80 | - Fix test incompatibility with mongoose@4.8.1 (#5) 81 | - version: 1.0.2 82 | date: 2017-02-06 83 | fixed: 84 | - Fix incompatibility with mongoose@4.8.1 (#5) 85 | - version: 1.0.1 86 | date: 2016-11-01 87 | fixed: 88 | - Fix find with tenantIds of type ObjectId. (#3) 89 | - version: 1.0.0 90 | date: 2016-06-26 91 | description: First Stable version 92 | added: 93 | - Introduce multi tenancy logic. 94 | - Test against real mongodb instance. 95 | - Display build badges in readme. 96 | - Setup coveralls in order to keep an eye on test coverage. 97 | - Improve code documentation. 98 | - Ensure coding standards via jshint. 99 | - version: 0.0.1 100 | date: 2016-06-21 101 | description: Project setup & initial release 102 | added: 103 | - Base mongoose plugin setup & tests. 104 | - Introduce MIT license. 105 | - Setup travis ci to run automated tests on every commit. 106 | -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 6, 3 | "node": true, 4 | "mocha": true 5 | } 6 | -------------------------------------------------------------------------------- /test/_utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost/mongo-tenant-test'; 11 | const mongoose = require('mongoose'); 12 | const mochaMongoose = require('mocha-mongoose'); 13 | const mongoTenantPlugin = require('../index.js'); 14 | const Schema = mongoose.Schema; 15 | 16 | let testModelUnifier = 0; 17 | 18 | mongoose.Promise = Promise; 19 | 20 | function createTestModel(schemaDefinition, options) { 21 | options = Object.assign({ 22 | applyOnSchema: void 0, 23 | mongoTenant: void 0, 24 | withPlugin: true 25 | }, options); 26 | 27 | let schema = new Schema(schemaDefinition, options.schemaOptions); 28 | 29 | if (typeof options.applyOnSchema === 'function') { 30 | options.applyOnSchema(schema); 31 | } 32 | 33 | if (options.withPlugin) { 34 | schema.plugin(mongoTenantPlugin, options.mongoTenant); 35 | } 36 | 37 | return mongoose.model(`mongoTenantTestModel${++testModelUnifier}`, schema); 38 | } 39 | 40 | function isMongoose4() { 41 | return mongoose.version[0] === '4'; 42 | } 43 | 44 | function clearDatabase() { 45 | mochaMongoose(MONGO_URI); 46 | 47 | beforeEach(function(done) { 48 | if (mongoose.connection.db) return done(); 49 | 50 | if (isMongoose4()) { 51 | mongoose.connect(MONGO_URI, { useMongoClient: true }, done); 52 | } else { 53 | mongoose.connect(MONGO_URI, done); 54 | } 55 | }); 56 | } 57 | 58 | function skipIf(condition, title, test) { 59 | if (condition) { 60 | return xit(title, test); 61 | } 62 | 63 | return it(title, test); 64 | } 65 | 66 | module.exports = { 67 | clearDatabase: clearDatabase, 68 | createTestModel: createTestModel, 69 | isMongoose4: isMongoose4, 70 | skipIf: skipIf, 71 | }; 72 | -------------------------------------------------------------------------------- /test/configuration.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const 11 | assert = require('chai').assert, 12 | mongoTenantPlugin = require('../index.js'); 13 | 14 | describe('MongoTenant', function() { 15 | describe('#Configuration', function() { 16 | it('plugin should be enabled by default.', function() { 17 | let mongoTenant = new mongoTenantPlugin.MongoTenant(); 18 | 19 | assert(mongoTenant.isEnabled() === true, 'Expected mongoTenant plugin to be enabled by default.'); 20 | }); 21 | 22 | it('plugin should be capable of being disabled.', function() { 23 | let mongoTenant = new mongoTenantPlugin.MongoTenant(null, { 24 | enabled: false 25 | }); 26 | 27 | assert(mongoTenant.isEnabled() === false, 'Expected mongoTenant plugin to be disabled.'); 28 | }); 29 | 30 | it('should have a default tenant id key of `tenantId`.', function() { 31 | let mongoTenant = new mongoTenantPlugin.MongoTenant(); 32 | 33 | assert.equal(mongoTenant.getTenantIdKey(), 'tenantId', 'Expected tenant id key to be `tenantId`.'); 34 | }); 35 | 36 | it('should be capable of setting a custom tenant id key.', function() { 37 | let mongoTenant = new mongoTenantPlugin.MongoTenant(null, { 38 | tenantIdKey: 'tenant_id' 39 | }); 40 | 41 | assert.equal(mongoTenant.getTenantIdKey(), 'tenant_id', 'Expected tenant id key to be `tenant_id`.'); 42 | }); 43 | 44 | it('should have a default tenant id field type of `String`.', function() { 45 | let mongoTenant = new mongoTenantPlugin.MongoTenant(); 46 | 47 | assert.equal(mongoTenant.getTenantIdType(), String, 'Expected tenant id field type to be `String`.'); 48 | }); 49 | 50 | it('should be capable of setting a custom tenant id field type.', function() { 51 | let mongoTenant = new mongoTenantPlugin.MongoTenant(null, { 52 | tenantIdType: Number 53 | }); 54 | 55 | assert.equal(mongoTenant.getTenantIdType(), Number, 'Expected tenant id field type to be `Number`.'); 56 | }); 57 | 58 | it('should have a default accessor method name of `byTenant`.', function() { 59 | let mongoTenant = new mongoTenantPlugin.MongoTenant(); 60 | 61 | assert.equal(mongoTenant.getAccessorMethod(), 'byTenant', 'Expected accessor method name to be `byTenant`.'); 62 | }); 63 | 64 | it('should be capable of setting a custom accessor method name.', function() { 65 | let mongoTenant = new mongoTenantPlugin.MongoTenant(null, { 66 | accessorMethod: 'tenancy' 67 | }); 68 | 69 | assert.equal(mongoTenant.getAccessorMethod(), 'tenancy', 'Expected accessor method name to be `tenancy`.'); 70 | }); 71 | 72 | it('should have a default tenant id getter method name of `getTenantId`.', function() { 73 | let mongoTenant = new mongoTenantPlugin.MongoTenant(); 74 | 75 | assert.equal(mongoTenant.getTenantIdGetter(), 'getTenantId', 'Expected tenant id getter method name to be `getTenantId`.'); 76 | }); 77 | 78 | it('should be capable of setting a custom tenant id getter method name.', function() { 79 | let mongoTenant = new mongoTenantPlugin.MongoTenant(null, { 80 | tenantIdGetter: 'get_tenant_id' 81 | }); 82 | 83 | assert.equal(mongoTenant.getTenantIdGetter(), 'get_tenant_id', 'Expected tenant id getter method name to be `get_tenant_id`.'); 84 | }); 85 | 86 | it('should not require tenant id field by default.', function() { 87 | let mongoTenant = new mongoTenantPlugin.MongoTenant(); 88 | 89 | assert.isFalse( 90 | mongoTenant.isTenantIdRequired(), 91 | 'Expected tenant id field to allow null values.' 92 | ); 93 | }); 94 | 95 | it('should be possible to set tenant id field required.', function() { 96 | let mongoTenant = new mongoTenantPlugin.MongoTenant(null, { 97 | requireTenantId: true, 98 | }); 99 | 100 | assert.isTrue( 101 | mongoTenant.isTenantIdRequired(), 102 | 'Expected tenant id field to be required (not nullable).' 103 | ); 104 | }); 105 | }); 106 | }); 107 | -------------------------------------------------------------------------------- /test/indexes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const 11 | assert = require('chai').assert, 12 | utils = require('./_utils'); 13 | 14 | 15 | describe('MongoTenant', function() { 16 | describe('#Indexes', function () { 17 | it('should consider the tenant id field in schema level unique indexes.', function() { 18 | let 19 | Model, 20 | indexesFound = {}; 21 | 22 | Model = utils.createTestModel({ 23 | field1: String, 24 | field2: Number 25 | }, { 26 | applyOnSchema: (schema) => { 27 | schema.index({field1:1}, {unique: true, name: 'index1'}); 28 | schema.index({field2:1}, {name: 'index2'}); 29 | schema.index({field1:1, field2: 1}, {unique: true, name: 'index3'}); 30 | } 31 | }); 32 | 33 | for (let index of Model.schema.indexes()) { 34 | if (index[1] && index[1].name) { 35 | indexesFound[index[1].name] = true; 36 | 37 | switch (index[1].name) { 38 | case 'index1': 39 | assert('tenantId' in index[0], 'Expected unique index1 to be extended by tenantId field.'); 40 | assert('field1' in index[0], 'Expected unique index1 to contain field1.'); 41 | break; 42 | case 'index2': 43 | assert(!('tenantId' in index[0]), 'Expected non unique index2 not to be extended by tenantId field.'); 44 | assert('field2' in index[0], 'Expected non unique index2 to contain field2.'); 45 | break; 46 | case 'index3': 47 | assert('tenantId' in index[0], 'Expected unique index3 to be extended by tenantId field.'); 48 | assert('field1' in index[0], 'Expected unique index3 to contain field1.'); 49 | assert('field2' in index[0], 'Expected unique index3 to contain field2.'); 50 | break; 51 | } 52 | } 53 | } 54 | 55 | assert(indexesFound.index1, 'Expected index1 to exist.'); 56 | assert(indexesFound.index2, 'Expected index2 to exist.'); 57 | assert(indexesFound.index3, 'Expected index3 to exist.'); 58 | }); 59 | 60 | it('should consider the tenant id field in field level unique indexes.', function() { 61 | let 62 | Model, indexesFound = {}; 63 | 64 | Model = utils.createTestModel({ 65 | field1: { 66 | type: String, 67 | unique: true 68 | }, 69 | field2: { 70 | type: Number, 71 | index: true 72 | } 73 | }); 74 | 75 | for (let index of Model.schema.indexes()) { 76 | if ('field1' in index[0]) { 77 | indexesFound.field1 = true; 78 | 79 | assert('tenantId' in index[0], 'Expected unique index on field1 to be extended by tenantId field.'); 80 | assert(!('field2' in index[0]), 'Expected unique index on field1 not to contain field2.'); 81 | } 82 | 83 | if ('field2' in index[0]) { 84 | indexesFound.field2 = true; 85 | 86 | assert(!('tenantId' in index[0]), 'Expected non unique index on field2 not to be extended by tenantId field.'); 87 | assert(!('field1' in index[0]), 'Expected non unique index on field2 not to contain field1.'); 88 | } 89 | } 90 | 91 | assert(indexesFound.field1, 'Expected index on field1 to exist.'); 92 | assert(indexesFound.field2, 'Expected index on field2 to exist.'); 93 | }); 94 | 95 | it('should consider the sparse property in field level unique indexes.', function() { 96 | let 97 | Model, indexesFound = {}; 98 | 99 | Model = utils.createTestModel({ 100 | field1: { 101 | type: String, 102 | unique: true, 103 | sparse: true 104 | }, 105 | field2: { 106 | type: Number, 107 | index: true 108 | } 109 | }); 110 | 111 | for (let index of Model.schema.indexes()) { 112 | if ('field1' in index[0]) { 113 | indexesFound.field1 = true; 114 | 115 | assert('sparse' in index[1], 'Expected sparse property option on field1.'); 116 | assert('tenantId' in index[0], 'Expected unique index on field1 to be extended by tenantId field.'); 117 | assert(!('field2' in index[0]), 'Expected unique index on field1 not to contain field2.'); 118 | } 119 | 120 | if ('field2' in index[0]) { 121 | indexesFound.field2 = true; 122 | 123 | assert(!('tenantId' in index[0]), 'Expected non unique index on field2 not to be extended by tenantId field.'); 124 | assert(!('field1' in index[0]), 'Expected non unique index on field2 not to contain field1.'); 125 | } 126 | } 127 | 128 | assert(indexesFound.field1, 'Expected index on field1 to exist.'); 129 | assert(indexesFound.field2, 'Expected index on field2 to exist.'); 130 | }); 131 | 132 | it('should consider the partialFilterExpression property in field level unique indexes.', function() { 133 | let 134 | Model, indexesFound = {}; 135 | 136 | Model = utils.createTestModel({ 137 | field1: { 138 | type: String, 139 | unique: true, 140 | partialFilterExpression: { field2: { $exists: true }} 141 | }, 142 | field2: { 143 | type: Number, 144 | index: true 145 | } 146 | }); 147 | 148 | for (let index of Model.schema.indexes()) { 149 | if ('field1' in index[0]) { 150 | indexesFound.field1 = true; 151 | 152 | assert('partialFilterExpression' in index[1], 'Expected partialFilterExpression property option on field1.'); 153 | assert('tenantId' in index[0], 'Expected unique index on field1 to be extended by tenantId field.'); 154 | assert(!('field2' in index[0]), 'Expected unique index on field1 not to contain field2.'); 155 | } 156 | 157 | if ('field2' in index[0]) { 158 | indexesFound.field2 = true; 159 | 160 | assert(!('tenantId' in index[0]), 'Expected non unique index on field2 not to be extended by tenantId field.'); 161 | assert(!('field1' in index[0]), 'Expected non unique index on field2 not to contain field1.'); 162 | } 163 | } 164 | 165 | assert(indexesFound.field1, 'Expected index on field1 to exist.'); 166 | assert(indexesFound.field2, 'Expected index on field2 to exist.'); 167 | }); 168 | }); 169 | }); 170 | -------------------------------------------------------------------------------- /test/integration.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const 11 | assert = require('chai').assert, 12 | utils = require('./_utils'); 13 | 14 | describe('MongoTenant', function() { 15 | describe('#Integration', function() { 16 | utils.clearDatabase(); 17 | 18 | it('should inject default accessor method.', function() { 19 | let Model = utils.createTestModel({}); 20 | 21 | assert(typeof Model.byTenant === 'function', 'Expected default accessor method to be statically available.'); 22 | }); 23 | 24 | it('should inject custom accessor method.', function() { 25 | let Model = utils.createTestModel({}, { 26 | mongoTenant: { 27 | accessorMethod: 'by_tenant' 28 | } 29 | }); 30 | 31 | assert(typeof Model.by_tenant === 'function', 'Expected custom accessor method `by_tenant` to be statically available.'); 32 | }); 33 | 34 | it('should expose its tenant binding.', function() { 35 | let 36 | Model = utils.createTestModel({}), 37 | ModelBoundToTenant = Model.byTenant(1); 38 | 39 | assert(ModelBoundToTenant.hasTenantContext === true, 'Expected static flag `hasTenantContext` on models bound to a certain tenant.'); 40 | assert((new ModelBoundToTenant()).hasTenantContext === true, 'Expected property `hasTenantContext` on model instances bound to a certain tenant.'); 41 | assert(typeof Model.hasTenantContext === 'undefined', 'Expected the mongoose model to be untouched.'); 42 | assert(typeof (new Model()).hasTenantContext === 'undefined', 'Expected the mongoose model to be untouched.'); 43 | }); 44 | 45 | it('should bind the model to the proper tenant.', function() { 46 | let 47 | Model = utils.createTestModel({}), 48 | modelA, modelB; 49 | 50 | modelA = Model.byTenant(1); 51 | modelB = Model.byTenant(2); 52 | 53 | assert.equal(modelA.getTenantId(), 1, 'Expected the tenantId of tenant specific model to be `1`.'); 54 | assert.equal((new modelA()).getTenantId(), 1, 'Expected the tenantId of tenant specific model to be `1`.'); 55 | assert.equal(modelB.getTenantId(), 2, 'Expected the tenantId of tenant specific model to be `2`.'); 56 | assert.equal((new modelB()).getTenantId(), 2, 'Expected the tenantId of tenant specific model to be `2`.'); 57 | }); 58 | 59 | it('should create tenant specific models only once and cache previous compilations.', function() { 60 | let 61 | Model = utils.createTestModel({}), 62 | modelA, modelB; 63 | 64 | assert.equal( 65 | Model.byTenant(1), Model.byTenant(1), 66 | 'Expected multiple calls to tenant specific model accessor to deliver same model compilation.' 67 | ); 68 | }); 69 | 70 | it('should bind Model.remove() to correct tenant context.', function(done) { 71 | let TestModel = utils.createTestModel({}); 72 | 73 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 74 | assert(!err, 'Expected creation of 2 test entities to work.'); 75 | 76 | TestModel.byTenant('tenant1').remove((err) => { 77 | assert(!err, 'Expected Model.remove() to work.'); 78 | 79 | TestModel.find({}, (err, entities) => { 80 | assert(!err, 'Expected Model.find() to work.'); 81 | assert.equal(entities.length, 1, 'Expected to find only one entity.'); 82 | assert.equal(entities[0].tenantId, 'tenant2', 'Expected tenant2 scope on entity.'); 83 | 84 | done(); 85 | }); 86 | }); 87 | }); 88 | }); 89 | 90 | it('should bind Model.aggregate(obj..., cb) to correct tenant context.', function(done) { 91 | let TestModel = utils.createTestModel({num: Number}); 92 | 93 | TestModel.create({tenantId: 'tenant1', num: 10}, {tenantId: 'tenant1', num: 12}, {tenantId: 'tenant2', num: 20}, (err) => { 94 | assert(!err, 'Expected creation of 3 test entities to work.'); 95 | 96 | TestModel.byTenant('tenant1').aggregate({ 97 | $group: { 98 | _id: '$tenantId', 99 | sum: {$sum: '$num'} 100 | }}, 101 | (err, results) => { 102 | assert(!err, 'Expected Model.aggregate() to work.'); 103 | assert.equal(results.length, 1, 'Expected model aggregation to return exactly one result.'); 104 | assert.equal(results[0].sum, 22, 'Expected the sum up `num` field for `tenant1` to be 22.'); 105 | assert.equal(results[0]._id, 'tenant1', 'Expected the tenant id of aggregated data ser to be `tenant1`.'); 106 | 107 | done(); 108 | } 109 | ); 110 | }); 111 | }); 112 | 113 | it('should bind Model.aggregate(obj[], func) to correct tenant context.', function(done) { 114 | let TestModel = utils.createTestModel({num: Number}); 115 | 116 | TestModel.create({tenantId: 'tenant1', num: 10}, {tenantId: 'tenant1', num: 12}, {tenantId: 'tenant2', num: 20}, (err) => { 117 | assert(!err, 'Expected creation of 3 test entities to work.'); 118 | 119 | TestModel.byTenant('tenant1').aggregate([{ 120 | $group: { 121 | _id: '$tenantId', 122 | sum: {$sum: '$num'} 123 | } 124 | }], 125 | (err, results) => { 126 | assert(!err, 'Expected Model.aggregate() to work.'); 127 | assert.equal(results.length, 1, 'Expected model aggregation to return exactly one result.'); 128 | assert.equal(results[0].sum, 22, 'Expected the sum up `num` field for `tenant1` to be 22.'); 129 | assert.equal(results[0]._id, 'tenant1', 'Expected the tenant id of aggregated data ser to be `tenant1`.'); 130 | 131 | done(); 132 | } 133 | ); 134 | }); 135 | }); 136 | 137 | it('should not be able to delete across tenants', (done) => { 138 | const TestModel = utils.createTestModel({ 139 | test: { 140 | type: String, 141 | required: true, 142 | trim: true 143 | }}); 144 | 145 | const ModelClassT1 = TestModel.byTenant('tenant1'); 146 | const ModelClassT2 = TestModel.byTenant('tenant2'); 147 | 148 | const t1Instance = new ModelClassT1({ test: 't1Instance' }); 149 | const t2Instance = new ModelClassT2({ test: 't2Instance' }); 150 | 151 | t1Instance.save((err1) => { 152 | assert(!err1, 'save t1 instance should work'); 153 | t2Instance.save((err2)=> { 154 | assert(!err2, 'save t2 instance should work'); 155 | ModelClassT2.deleteOne({ _id: t1Instance._id}, (err) => { 156 | assert(!err, 'error should occour'); // I guess it's fine that no error occours. that is just mongo behaviour 157 | // however the document should not be deleted, since ModelClassT2 should have no access to elements of tenant1 158 | ModelClassT1.findOne(t1Instance._id, (err, modelInst) => { 159 | assert(modelInst, 'modelInstance should still be available, since it should not be able to delete across tenants'); 160 | done(); 161 | }); 162 | }); 163 | }); 164 | }); 165 | }); 166 | 167 | it('should bind Model.deleteOne(conditions, cb) to correct tenant context.', function(done) { 168 | let TestModel = utils.createTestModel({}); 169 | 170 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 171 | assert(!err, 'Expected creation of 2 test entities to work.'); 172 | 173 | TestModel.byTenant('tenant1').deleteOne({tenantId: 'tenant2'}, (deletionError) => { 174 | assert(!deletionError, 'Expected Model.deleteMany() to work'); 175 | 176 | TestModel.find({}, (lookupErr, entities) => { 177 | assert(!lookupErr, 'Expected Model.find() to work.'); 178 | assert.equal(entities.length, 1, 'Expected to find only one entity.'); 179 | assert.equal(entities[0].tenantId, 'tenant2', 'Expected tenant2 scope on entity.'); 180 | 181 | done(); 182 | }); 183 | }); 184 | }); 185 | }); 186 | 187 | it('should bind Model.deleteMany(conditions, options, cb) to correct tenant context.', function(done) { 188 | let TestModel = utils.createTestModel({num: Number}); 189 | 190 | TestModel.create({tenantId: 'tenant1', num: 1}, {tenantId: 'tenant1', num: 1}, {tenantId: 'tenant2', num: 1}, (err) => { 191 | assert(!err, 'Expected creation of 3 test entities to work.'); 192 | 193 | TestModel.byTenant('tenant1').deleteMany({num: 1}, (deletionError) => { 194 | assert(!deletionError, 'Expected Model.deleteMany() to work'); 195 | 196 | TestModel.find({}, (lookupErr, entities) => { 197 | assert(!lookupErr, 'Expected Model.find() to work.'); 198 | assert.equal(entities.length, 1, 'Expected to find only one entity.'); 199 | assert.equal(entities[0].tenantId, 'tenant2', 'Expected tenant2 scope on entity.'); 200 | 201 | done(); 202 | }); 203 | }); 204 | }); 205 | }); 206 | }); 207 | }); 208 | -------------------------------------------------------------------------------- /test/middleware.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const 11 | assert = require('chai').assert, 12 | utils = require('./_utils'), 13 | Schema = require('mongoose').Schema; 14 | 15 | describe('MongoTenant', function() { 16 | describe('#Middleware', function() { 17 | utils.clearDatabase(); 18 | 19 | it('should add tenant on all discriminators of a model', function (done) { 20 | let 21 | TestModel = utils.createTestModel({ kind: String }, { 22 | schemaOptions : { discriminatorKey: 'kind' } 23 | }); 24 | 25 | TestModel.discriminator('disc_key', new Schema({ inherit: Boolean })); 26 | 27 | TestModel.byTenant(1).create({ inherit: true, kind: 'disc_key' }, (err, doc) => { 28 | assert.equal(doc.tenantId, 1); 29 | assert.equal(doc.inherit, true, 'does not inherit'); 30 | assert.equal(doc.kind, 'disc_key'); 31 | done(); 32 | }); 33 | }); 34 | 35 | it('should inherit properties from Model when using discriminator', function (done) { 36 | let 37 | TestModel = utils.createTestModel({ kind: String }); 38 | 39 | let 40 | DiscriminatorTest = utils.createTestModel({ inherit: Boolean }); 41 | 42 | DiscriminatorTest = TestModel.discriminator('DiscriminatorTest', DiscriminatorTest.schema); 43 | 44 | DiscriminatorTest.byTenant(1).create({ inherit: true, kind: 'test' }, (err, doc) => { 45 | assert.equal(doc.__t, 'DiscriminatorTest'); 46 | assert.equal(doc.tenantId, 1); 47 | assert(doc.inherit); 48 | assert.equal(doc.kind, 'test'); 49 | done(); 50 | }); 51 | }); 52 | 53 | utils.skipIf(utils.isMongoose4(), 'should bind tenant context to Model.countDocuments().', function(done) { 54 | let TestModel = utils.createTestModel({}); 55 | 56 | TestModel.byTenant(1).create({}, {}, {}, (err) => { 57 | assert(!err, 'Expected creation of 3 test entities to work.'); 58 | 59 | TestModel.byTenant(1).countDocuments((err, count) => { 60 | assert(!err, 'Expected entity counting to work.'); 61 | assert.equal(count, 3, 'Expected 3 entries for tenant `1`.'); 62 | 63 | TestModel.byTenant(2).countDocuments((err, count) => { 64 | assert(!err, 'Expected entity counting to work.'); 65 | assert.equal(count, 0, 'Expected 0 entries for tenant `2`.'); 66 | 67 | done(); 68 | }); 69 | }); 70 | }); 71 | }); 72 | 73 | it('should bind tenant context to Model.count().', function(done) { 74 | let 75 | TestModel = utils.createTestModel({}); 76 | 77 | TestModel.byTenant(1).create({}, {}, {}, (err) => { 78 | assert(!err, 'Expected creation of 3 test entities to work.'); 79 | 80 | TestModel.byTenant(1).count((err, count) => { 81 | assert(!err, 'Expected entity counting to work.'); 82 | assert.equal(count, 3, 'Expected 3 entries for tenant `1`.'); 83 | 84 | TestModel.byTenant(2).count((err, count) => { 85 | assert(!err, 'Expected entity counting to work.'); 86 | assert.equal(count, 0, 'Expected 0 entries for tenant `2`.'); 87 | 88 | done(); 89 | }); 90 | }); 91 | }); 92 | }); 93 | 94 | utils.skipIf(utils.isMongoose4(), 'should avoid tenant context jumping on Model.countDocuments().', function(done) { 95 | let TestModel = utils.createTestModel({}); 96 | 97 | TestModel.byTenant(1).create({}, {}, {}, (err) => { 98 | assert(!err, 'Expected creation of 3 test entities to work.'); 99 | 100 | TestModel.byTenant(2).countDocuments({tenantId: 1}, (err, count) => { 101 | assert(!err, 'Expected entity counting to work.'); 102 | assert.equal(count, 0, 'Expected 0 entries for tenant `2`.'); 103 | 104 | TestModel.byTenant(1).countDocuments({tenantId: 2}, (err, count) => { 105 | assert(!err, 'Expected entity counting to work.'); 106 | assert.equal(count, 3, 'Expected 3 entries for tenant `1`.'); 107 | 108 | done(); 109 | }); 110 | }); 111 | }); 112 | }); 113 | 114 | it('should avoid tenant context jumping on Model.count().', function(done) { 115 | let 116 | TestModel = utils.createTestModel({}); 117 | 118 | TestModel.byTenant(1).create({}, {}, {}, (err) => { 119 | assert(!err, 'Expected creation of 3 test entities to work.'); 120 | 121 | TestModel.byTenant(2).count({tenantId: 1}, (err, count) => { 122 | assert(!err, 'Expected entity counting to work.'); 123 | assert.equal(count, 0, 'Expected 0 entries for tenant `2`.'); 124 | 125 | TestModel.byTenant(1).count({tenantId: 2}, (err, count) => { 126 | assert(!err, 'Expected entity counting to work.'); 127 | assert.equal(count, 3, 'Expected 3 entries for tenant `1`.'); 128 | 129 | done(); 130 | }); 131 | }); 132 | }); 133 | }); 134 | 135 | utils.skipIf(utils.isMongoose4(), 'should not affect Model.countDocuments() when not in tenant context.', function(done) { 136 | let TestModel = utils.createTestModel({}); 137 | 138 | TestModel.create({tenantId: 1}, {tenantId: 2}, {tenantId: 3}, (err) => { 139 | assert(!err, 'Expected creation of 3 test entities to work.'); 140 | 141 | TestModel.countDocuments((err, count) => { 142 | assert(!err, 'Expected entity counting to work.'); 143 | assert.equal(count, 3, 'Expected 3 entries for all tenants.'); 144 | 145 | done(); 146 | }); 147 | }); 148 | }); 149 | 150 | it('should not affect Model.count() when not in tenant context.', function(done) { 151 | let TestModel = utils.createTestModel({}); 152 | 153 | TestModel.create({tenantId: 1}, {tenantId: 2}, {tenantId: 3}, (err) => { 154 | assert(!err, 'Expected creation of 3 test entities to work.'); 155 | 156 | TestModel.count((err, count) => { 157 | assert(!err, 'Expected entity counting to work.'); 158 | assert.equal(count, 3, 'Expected 3 entries for all tenants.'); 159 | 160 | done(); 161 | }); 162 | }); 163 | }); 164 | 165 | it('should bind tenant context to Model.find().', function(done) { 166 | let 167 | TestModel = utils.createTestModel({}); 168 | 169 | TestModel.byTenant('tenant1').create({}, {}, {}, (err) => { 170 | assert(!err, 'Expected creation of 3 test entities to work.'); 171 | 172 | TestModel.byTenant('tenant1').find({}, (err, entities) => { 173 | assert(!err, 'Expected entity search to work.'); 174 | assert.equal(entities.length, 3, 'Expected to find 3 entities for `tenant1`.'); 175 | 176 | TestModel.byTenant('tenant2').find({}, (err, entities) => { 177 | assert(!err, 'Expected entity search to work.'); 178 | assert.equal(entities.length, 0, 'Expected to find no entities for `tenant2`.'); 179 | 180 | done(); 181 | }); 182 | }); 183 | }); 184 | }); 185 | 186 | it('should avoid tenant context jumping on Model.find().', function(done) { 187 | let 188 | TestModel = utils.createTestModel({}); 189 | 190 | TestModel.byTenant('tenant1').create({}, {}, {}, (err) => { 191 | assert(!err, 'Expected creation of 3 test entities to work.'); 192 | 193 | TestModel.byTenant('tenant2').find({tenantId: 'tenant1'}, (err, entities) => { 194 | assert(!err, 'Expected entity search to work.'); 195 | assert.equal(entities.length, 0, 'Expected to find 0 entities for `tenant2`.'); 196 | 197 | TestModel.byTenant('tenant1').find({tenantId: 'tenant2'}, (err, entities) => { 198 | assert(!err, 'Expected entity search to work.'); 199 | assert.equal(entities.length, 3, 'Expected to find 3 entities for `tenant1`.'); 200 | 201 | done(); 202 | }); 203 | }); 204 | }); 205 | }); 206 | 207 | it('should pass down tenant context on Model.find().populate()', function (done) { 208 | const ChildModel = utils.createTestModel({}); 209 | const ParentModel = utils.createTestModel({ 210 | childs: [{ type: Schema.Types.ObjectId, ref: ChildModel.modelName }], 211 | }); 212 | 213 | ChildModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err, child1, child2) => { 214 | assert(!err, 'Expected creation of 2 child test entities to work.'); 215 | 216 | ParentModel.create({tenantId: 'tenant1', childs: [child1._id, child2._id]}, (err) => { 217 | assert(!err, 'Expected creation of 1 parent test entity to work.'); 218 | 219 | ParentModel.byTenant('tenant1').find().populate('childs').exec((err, matches) => { 220 | assert(!err, 'Expected entity search by `Model.find` to work.'); 221 | assert.equal(matches.length, 1, 'Expected to find exactly 1 parent entity.'); 222 | 223 | const parent = matches[0]; 224 | assert.equal(parent.childs.length, 1, 'Expected exactly 1 child in found parent entity.'); 225 | assert.equal(parent.childs[0].tenantId, 'tenant1', 'Expected child of found parent entity to be of same tenant.'); 226 | 227 | done(); 228 | }); 229 | }); 230 | }); 231 | }); 232 | 233 | it('should not pass down tenant context on Model.find().populate() if referenced model is not tenant based', function (done) { 234 | const ChildModel = utils.createTestModel({}, {withPlugin: false}); 235 | const ParentModel = utils.createTestModel({ 236 | childs: [{ type: Schema.Types.ObjectId, ref: ChildModel.modelName }], 237 | }); 238 | 239 | ChildModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err, child1, child2) => { 240 | assert(!err, 'Expected creation of 2 child test entities to work.'); 241 | 242 | ParentModel.create({tenantId: 'tenant1', childs: [child1._id, child2._id]}, (err) => { 243 | assert(!err, 'Expected creation of 1 parent test entity to work.'); 244 | 245 | ParentModel.byTenant('tenant1').find().populate('childs').exec((err, matches) => { 246 | assert(!err, 'Expected entity search by `Model.find` to work.'); 247 | assert.equal(matches.length, 1, 'Expected to find exactly 1 parent entity.'); 248 | 249 | const parent = matches[0]; 250 | assert.equal(parent.childs.length, 2, 'Expected exactly 2 childs in found parent entity.'); 251 | assert.equal(parent.childs[0].hasTenantContext, void 0, 'Expected first child to not have a tenant context.'); 252 | assert.equal(parent.childs[1].hasTenantContext, void 0, 'Expected second child to not have a tenant context.'); 253 | done(); 254 | }); 255 | }); 256 | }); 257 | }); 258 | 259 | it('should not pass down tenant context on Model.find().populate() if referenced model has different tenant level', function (done) { 260 | const ChildModel = utils.createTestModel({}, { 261 | mongoTenant: { tenantIdKey: 'otherTenantId' }, 262 | }); 263 | const ParentModel = utils.createTestModel({ 264 | childs: [{ type: Schema.Types.ObjectId, ref: ChildModel.modelName }], 265 | }); 266 | 267 | ChildModel.create({otherTenantId: 'tenant1'}, {otherTenantId: 'tenant2'}, (err, child1, child2) => { 268 | assert(!err, 'Expected creation of 2 child test entities to work.'); 269 | 270 | ParentModel.create({tenantId: 'tenant1', childs: [child1._id, child2._id]}, (err) => { 271 | assert(!err, 'Expected creation of 1 parent test entity to work.'); 272 | 273 | ParentModel.byTenant('tenant1').find().populate('childs').exec((err, matches) => { 274 | assert(!err, 'Expected entity search by `Model.find` to work.'); 275 | assert.equal(matches.length, 1, 'Expected to find exactly 1 parent entity.'); 276 | 277 | const parent = matches[0]; 278 | assert.equal(parent.childs.length, 2, 'Expected exactly 2 childs in found parent entity.'); 279 | assert.equal(parent.childs[0].hasTenantContext, void 0, 'Expected first child to not have a tenant context.'); 280 | assert.equal(parent.childs[1].hasTenantContext, void 0, 'Expected second child to not have a tenant context.'); 281 | done(); 282 | }); 283 | }); 284 | }); 285 | }); 286 | 287 | it('should bind tenant context to Model.findOne().', function(done) { 288 | let TestModel = utils.createTestModel({}); 289 | 290 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, {tenantId: 'tenant3'}, (err) => { 291 | assert(!err, 'Expected creation of 3 test entities to work.'); 292 | 293 | TestModel.byTenant('tenant1').findOne((err, model) => { 294 | assert(!err, 'Expected entity search by `Model.findOne` to work.'); 295 | assert.equal(model.tenantId, 'tenant1', 'Expected the found entity to be bound to the correct tenant.'); 296 | 297 | TestModel.byTenant('tenant4').findOne((err, model) => { 298 | assert(!err, 'Expected entity search by `Model.findOne` to work.'); 299 | assert(!model, 'Expected the found no entity in the context of `tenant4`.'); 300 | 301 | done(); 302 | }); 303 | }); 304 | }); 305 | }); 306 | 307 | it('should avoid tenant context jumping on Model.findOne().', function(done) { 308 | let 309 | TestModel = utils.createTestModel({}); 310 | 311 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, {tenantId: 'tenant3'}, (err) => { 312 | assert(!err, 'Expected creation of 3 test entities to work.'); 313 | 314 | TestModel.byTenant('tenant1').findOne({tenantId: 'tenant2'}, (err, model) => { 315 | assert(!err, 'Expected entity search by `Model.findOne` to work.'); 316 | assert.equal(model.tenantId, 'tenant1', 'Expected the found entity to be bound to the correct tenant.'); 317 | 318 | TestModel.byTenant('tenant4').findOne({tenantId: 'tenant1'}, (err, model) => { 319 | assert(!err, 'Expected entity search by `Model.findOne` to work.'); 320 | assert(!model, 'Expected to find no entity in the context of `tenant4`.'); 321 | 322 | done(); 323 | }); 324 | }); 325 | }); 326 | }); 327 | 328 | it('should bind tenant context to Model.findOneAndRemove().', function(done) { 329 | let 330 | TestModel = utils.createTestModel({}); 331 | 332 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, {tenantId: 'tenant3'}, (err) => { 333 | assert(!err, 'Expected creation of 3 test entities to work.'); 334 | 335 | TestModel.byTenant('tenant1').findOneAndRemove({}, (err, model) => { 336 | assert(!err, 'Expected method `Model.findOneAndRemove` to work.'); 337 | assert.equal(model.tenantId, 'tenant1', 'Expected the removed entity to be bound to the correct tenant.'); 338 | 339 | TestModel.byTenant('tenant4').findOneAndRemove({}, (err, model) => { 340 | assert(!err, 'Expected method `Model.findOneAndRemove` to work.'); 341 | assert(!model, 'Expected to removed no entity in the context of `tenant4`.'); 342 | 343 | done(); 344 | }); 345 | }); 346 | }); 347 | }); 348 | 349 | it('should bind tenant context to Model.findOneAndUpdate().', function(done) { 350 | let TestModel = utils.createTestModel({someField: String}); 351 | 352 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 353 | assert(!err, 'Expected creation of 2 test entities to work.'); 354 | 355 | TestModel.byTenant('tenant1').findOneAndUpdate({}, {someField: 'some-value'}, {'new': true}, (err, entity) => { 356 | assert(!err, 'Expected Model.findOneAndUpdate to work.'); 357 | assert.equal(entity.tenantId, 'tenant1', 'Expected the found entity to be bound to the correct tenant.'); 358 | assert.equal(entity.someField, 'some-value', 'Expected the updated entity to have someField set to some-value'); 359 | 360 | TestModel.byTenant('tenant3').findOneAndUpdate({}, {someField: 'some-value'}, (err, entity) => { 361 | assert(!err, 'Expected Model.findOneAndUpdate to work.'); 362 | assert(!entity, 'Expected to not update any entity for tenant4.'); 363 | 364 | done(); 365 | }); 366 | }); 367 | }); 368 | }); 369 | 370 | it('should bind tenant context to Model.save().', function(done) { 371 | let 372 | Model = utils.createTestModel({}).byTenant(1), 373 | model = new Model(); 374 | 375 | model.save((err, obj) => { 376 | assert(!err, 'Expected model persistance to work'); 377 | assert.equal(obj.tenantId, 1, 'Expected tenantId to be automatically set to `1`.'); 378 | 379 | done(); 380 | }); 381 | }); 382 | 383 | it('should avoid tenant jumping on Model.save().', function(done) { 384 | let 385 | Model = utils.createTestModel({}).byTenant(1), 386 | model = new Model(); 387 | 388 | model.set('tenantId', 2); 389 | 390 | model.save((err, obj) => { 391 | assert(!err, 'Expected model persistance to work'); 392 | assert.equal(obj.tenantId, 1, 'Expected tenantId to be automatically set to `1`.'); 393 | 394 | done(); 395 | }); 396 | }); 397 | 398 | it('should bind custom tenant key context to static Model.create() method.', function(done) { 399 | let Model = utils.createTestModel({}, { 400 | mongoTenant: { tenantIdKey: 'customTenantId' } 401 | }).byTenant(1); 402 | 403 | Model.create({}, (err, obj) => { 404 | assert(!err, 'Expected model persistance to work'); 405 | assert.equal(obj.customTenantId, 1, 'Expected customTenantId to be automatically set to `1`.'); 406 | 407 | done(); 408 | }); 409 | }); 410 | 411 | it('should avoid custom tenant key jumping on static Model.create() method.', function(done) { 412 | let Model = utils.createTestModel({}, { 413 | mongoTenant: { tenantIdKey: 'customTenantId' } 414 | }).byTenant(1); 415 | 416 | Model.create({ customTenantId: 2 }, (err, obj) => { 417 | assert(!err, 'Expected model persistance to work'); 418 | assert.equal(obj.customTenantId, 1, 'Expected customTenantId to be automatically set to `1`.'); 419 | 420 | done(); 421 | }); 422 | }); 423 | 424 | it('should bind tenant context to static Model.create() method.', function(done) { 425 | let 426 | Model = utils.createTestModel({}).byTenant(1); 427 | 428 | Model.create({}, (err, obj) => { 429 | assert(!err, 'Expected model persistance to work'); 430 | assert.equal(obj.tenantId, 1, 'Expected tenantId to be automatically set to `1`.'); 431 | 432 | done(); 433 | }); 434 | }); 435 | 436 | it('should avoid tenant jumping on static Model.create() method.', function(done) { 437 | let 438 | Model = utils.createTestModel({}).byTenant(1); 439 | 440 | Model.create({tenantId: 2}, (err, obj) => { 441 | assert(!err, 'Expected model persistance to work'); 442 | assert.equal(obj.tenantId, 1, 'Expected tenantId to be automatically set to `1`.'); 443 | 444 | done(); 445 | }); 446 | }); 447 | 448 | it('should bind tenant context to documents created by Model.insertMany() method.', function(done) { 449 | let 450 | Model = utils.createTestModel({}).byTenant(1); 451 | 452 | Model.insertMany([{}, {}], (err, docs) => { 453 | assert(!err, 'Expected insertMany to work'); 454 | 455 | docs.forEach(function(obj) { 456 | assert.ok(obj.hasTenantContext); 457 | assert.equal(obj.tenantId, 1, 'Expected tenantId to be automatically set to `1`.'); 458 | }); 459 | 460 | done(); 461 | }); 462 | }); 463 | 464 | it('should bind tenant context to documents created by Model.insertMany() method.', function(done) { 465 | let 466 | Model = utils.createTestModel({}).byTenant(1); 467 | 468 | Model.insertMany([{tenantId: 2}, {tenantId: -3}, {tenantId: '2'}], (err, docs) => { 469 | assert(!err, 'Expected insertMany to work'); 470 | 471 | docs.forEach(function(obj) { 472 | assert.ok(obj.hasTenantContext); 473 | assert.equal(obj.tenantId, 1, 'Expected tenantId to be automatically set to `1`.'); 474 | }); 475 | 476 | done(); 477 | }); 478 | }); 479 | 480 | it('should bind tenant context to a single document created by Model.insertMany() method.', function(done) { 481 | let 482 | Model = utils.createTestModel({}).byTenant(1); 483 | 484 | Model.insertMany({tenantId: 2}, (err, docs) => { 485 | assert(!err, 'Expected insertMany to work'); 486 | 487 | docs.forEach(function(obj) { 488 | assert.ok(obj.hasTenantContext); 489 | assert.equal(obj.tenantId, 1, 'Expected tenantId to be automatically set to `1`.'); 490 | }); 491 | 492 | done(); 493 | }); 494 | }); 495 | 496 | it('Model.insertMany() method should fail properly.', function(done) { 497 | let 498 | Model = utils.createTestModel({}).byTenant(1); 499 | 500 | const promise = Model.insertMany([{field: 'A'}, {_id: 'A'}], (err, docs) => { 501 | assert(err, 'Expected insertMany to fail'); 502 | assert(!docs, 'Expected docs to be undefined on failed insertMany calls.'); 503 | 504 | done(); 505 | }); 506 | 507 | // compatibility for mongoose 4 & 5 508 | if (promise && promise.catch) { 509 | promise.catch(() => {}); 510 | } 511 | }); 512 | 513 | it('Model.insertMany() method should work without tenant context.', function(done) { 514 | let 515 | Model = utils.createTestModel({}); 516 | 517 | Model.insertMany([{tenantId: 1}, {tenantId: 2}], (err, docs) => { 518 | assert(!err, 'Expected insertMany to work'); 519 | assert(docs.length === 2, 'Expected 2 docs to be inserted.'); 520 | assert.equal(docs[0].tenantId, 1, 'Expected the first document to have a tenantId property of `1`.'); 521 | assert.equal(docs[1].tenantId, 2, 'Expected the first document to have a tenantId property of `2`.'); 522 | 523 | docs.forEach(function(doc) { 524 | assert(doc instanceof Model, 'Expected inserted documents to be proper instances of the model.'); 525 | }); 526 | 527 | done(); 528 | }); 529 | }); 530 | 531 | it('should bind tenant context to Model.update().', function(done) { 532 | let TestModel = utils.createTestModel({someField: String}); 533 | 534 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 535 | assert(!err, 'Expected creation of 2 test entities to work.'); 536 | 537 | TestModel.byTenant('tenant1').update({}, {someField: 'some-value'}, (err) => { 538 | assert(!err, 'Expected model update to work.'); 539 | 540 | TestModel.byTenant('tenant1').find({}, (err, entities) => { 541 | assert(!err, 'Expected entity search by Model.find to work.'); 542 | 543 | for (let entity of entities) { 544 | assert.equal(entity.someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 545 | } 546 | 547 | done(); 548 | }); 549 | }); 550 | }); 551 | }); 552 | 553 | it('should avoid overwriting tenant context on Model.update().', function(done) { 554 | let TestModel = utils.createTestModel({someField: String}); 555 | 556 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 557 | assert(!err, 'Expected creation of 2 test entities to work.'); 558 | 559 | TestModel.byTenant('tenant1').update({}, { 560 | tenantId: 'tenant2', 561 | someField: 'some-value', 562 | $set: { tenantId: "tenant2" } 563 | }, (err) => { 564 | assert(!err, 'Expected model update to work.'); 565 | 566 | TestModel.byTenant('tenant1').find({}, (err, entities) => { 567 | assert(!err, 'Expected entity search by Model.find to work.'); 568 | assert.equal(entities.length, 1, 'Expected to find exactly 1 entity.'); 569 | assert.equal(entities[0].someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 570 | 571 | done(); 572 | }); 573 | }); 574 | }); 575 | }); 576 | 577 | it('should preserve tenant context on Model.update() with truthy overwrite option.', function(done) { 578 | let TestModel = utils.createTestModel({someField: String}); 579 | 580 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 581 | assert(!err, 'Expected creation of 2 test entities to work.'); 582 | 583 | TestModel.byTenant('tenant1').update({}, {tenantId: 'tenant2', someField: 'some-value'}, {overwrite: true}, (err) => { 584 | assert(!err, 'Expected model update to work.'); 585 | 586 | TestModel.byTenant('tenant1').find({}, (err, entities) => { 587 | assert(!err, 'Expected entity search by Model.find to work.'); 588 | assert.equal(entities.length, 1, 'Expected to find exactly 1 entity.'); 589 | assert.equal(entities[0].someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 590 | 591 | done(); 592 | }); 593 | }); 594 | }); 595 | }); 596 | 597 | it('should not affect Model.update() when not in tenant context.', function(done) { 598 | let TestModel = utils.createTestModel({someField: String}); 599 | 600 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2', someField: 'some-value'}, (err) => { 601 | assert(!err, 'Expected creation of 2 test entities to work.'); 602 | 603 | TestModel.update({tenantId: 'tenant1'}, {tenantId: 'tenant2', someField: 'some-value'}, (err) => { 604 | assert(!err, 'Expected model update to work.'); 605 | 606 | TestModel.find({}, (err, entities) => { 607 | assert(!err, 'Expected entity search by Model.find to work.'); 608 | assert.equal(entities.length, 2, 'Expected to find exactly 2 entity.'); 609 | assert.equal(entities[0].someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 610 | assert.equal(entities[0].tenantId, 'tenant2', 'Expected updated tenantId to be `tenant2`.'); 611 | assert.equal(entities[1].someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 612 | assert.equal(entities[1].tenantId, 'tenant2', 'Expected updated tenantId to be `tenant2`.'); 613 | 614 | done(); 615 | }); 616 | }); 617 | }); 618 | }); 619 | 620 | it('should bind tenant context to Model.updateMany().', function(done) { 621 | let TestModel = utils.createTestModel({someField: String}); 622 | 623 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 624 | assert(!err, 'Expected creation of 2 test entities to work.'); 625 | 626 | TestModel.byTenant('tenant1').updateMany({}, {someField: 'some-value'}, (err) => { 627 | assert(!err, 'Expected model updateMany to work.'); 628 | 629 | TestModel.byTenant('tenant1').find({}, (err, entities) => { 630 | assert(!err, 'Expected entity search by Model.find to work.'); 631 | 632 | for (let entity of entities) { 633 | assert.equal(entity.someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 634 | } 635 | 636 | done(); 637 | }); 638 | }); 639 | }); 640 | }); 641 | 642 | it('should avoid overwriting tenant context on Model.updateMany().', function(done) { 643 | let TestModel = utils.createTestModel({someField: String}); 644 | 645 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2'}, (err) => { 646 | assert(!err, 'Expected creation of 2 test entities to work.'); 647 | 648 | TestModel.byTenant('tenant1').updateMany({}, { 649 | tenantId: 'tenant2', 650 | someField: 'some-value', 651 | $set: { tenantId: "tenant2" } 652 | }, (err) => { 653 | assert(!err, 'Expected model updateMany to work.'); 654 | 655 | TestModel.byTenant('tenant1').find({}, (err, entities) => { 656 | assert(!err, 'Expected entity search by Model.find to work.'); 657 | assert.equal(entities.length, 1, 'Expected to find exactly 1 entity.'); 658 | assert.equal(entities[0].someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 659 | 660 | done(); 661 | }); 662 | }); 663 | }); 664 | }); 665 | 666 | it('should not affect Model.updateMany() when not in tenant context.', function(done) { 667 | let TestModel = utils.createTestModel({someField: String}); 668 | 669 | TestModel.create({tenantId: 'tenant1'}, {tenantId: 'tenant2', someField: 'some-value'}, (err) => { 670 | assert(!err, 'Expected creation of 2 test entities to work.'); 671 | 672 | TestModel.updateMany({tenantId: 'tenant1'}, {tenantId: 'tenant2', someField: 'some-value'}, (err) => { 673 | assert(!err, 'Expected model updateMany to work.'); 674 | 675 | TestModel.find({}, (err, entities) => { 676 | assert(!err, 'Expected entity search by Model.find to work.'); 677 | assert.equal(entities.length, 2, 'Expected to find exactly 2 entity.'); 678 | assert.equal(entities[0].someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 679 | assert.equal(entities[0].tenantId, 'tenant2', 'Expected updated tenantId to be `tenant2`.'); 680 | assert.equal(entities[1].someField, 'some-value', 'Expected updated value of someField to be `some-value`.'); 681 | assert.equal(entities[1].tenantId, 'tenant2', 'Expected updated tenantId to be `tenant2`.'); 682 | 683 | done(); 684 | }); 685 | }); 686 | }); 687 | }); 688 | }); 689 | }); 690 | -------------------------------------------------------------------------------- /test/opt-out.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const 11 | assert = require('chai').assert, 12 | utils = require('./_utils'); 13 | 14 | describe('MongoTenant', function() { 15 | describe('#Opt-Out', function() { 16 | it('accessor method should deliver default mongoose model when mongoTenant is disabled.', function() { 17 | let Model = utils.createTestModel({}, { 18 | mongoTenant: { 19 | enabled: false 20 | } 21 | }); 22 | 23 | assert(typeof Model.byTenant === 'function', 'Expected accessor method to be available.'); 24 | assert(typeof Model.byTenant(1).getTenantId === 'undefined', 'Expected default mongoose model when mongoTenant is disabled.'); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const 11 | assert = require('chai').assert, 12 | mongoose = require('mongoose'), 13 | mongoTenant = require('../index'); 14 | 15 | describe('MongoTenant', function() { 16 | describe('#Plugin', function() { 17 | it('should have correct mongoose plugin signature.', function() { 18 | assert(typeof mongoTenant === 'function', 'Expected mongo-tenant to be a function.'); 19 | }); 20 | 21 | it('should register as mongoose schema plugin.', function() { 22 | let testSchema = new mongoose.Schema({}); 23 | 24 | assert.doesNotThrow(() => { 25 | testSchema.plugin(mongoTenant); 26 | }); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/require-tenant-id.js: -------------------------------------------------------------------------------- 1 | /** 2 | * mongo-tenant - Multi-tenancy for mongoose on document level. 3 | * 4 | * @copyright Copyright (c) 2016-2017, craftup 5 | * @license https://github.com/craftup/node-mongo-tenant/blob/master/LICENSE MIT 6 | */ 7 | 8 | 'use strict'; 9 | 10 | const 11 | assert = require('chai').assert, 12 | utils = require('./_utils'); 13 | 14 | describe('MongoTenant', function() { 15 | describe('requireTenantId', function() { 16 | utils.clearDatabase(); 17 | 18 | it('should allow a nullable tenant id by default.', function(next) { 19 | const TestModel = utils.createTestModel({}); 20 | 21 | TestModel.byTenant(null).create({}, function(err, model) { 22 | assert(!err, 'Expected creation of 1 test entity to work.'); 23 | assert(!model.getTenantId()); 24 | 25 | next(); 26 | }); 27 | }); 28 | 29 | it('should allow an undefined tenant id by default.', function(next) { 30 | const TestModel = utils.createTestModel({}); 31 | 32 | TestModel.byTenant(undefined).create({}, function(err, model) { 33 | assert(!err, 'Expected creation of 1 test entity to work.'); 34 | assert(!model.getTenantId()); 35 | 36 | next(); 37 | }); 38 | }); 39 | 40 | it('should not allow a nullable tenant id when tenant id is required.', function(next) { 41 | const TestModel = utils.createTestModel({}, { 42 | mongoTenant: { 43 | requireTenantId: true, 44 | }, 45 | }); 46 | 47 | TestModel.byTenant(null).create({}, function(err) { 48 | assert(err, 'Expected creation of 1 test entity to fail.'); 49 | 50 | next(); 51 | }); 52 | }); 53 | 54 | it('should not allow an undefined tenant id when tenant id is required.', function(next) { 55 | const TestModel = utils.createTestModel({}, { 56 | mongoTenant: { 57 | requireTenantId: true, 58 | }, 59 | }); 60 | 61 | TestModel.byTenant(undefined).create({}, function(err) { 62 | assert(err, 'Expected creation of 1 test entity no fail.'); 63 | 64 | next(); 65 | }); 66 | }); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@release-notes/changelog-parser@^0.1.2": 6 | version "0.1.2" 7 | resolved "https://registry.yarnpkg.com/@release-notes/changelog-parser/-/changelog-parser-0.1.2.tgz#15fe8ae9b103b4890e370b1a5a2f0e735d992667" 8 | integrity sha512-sDV94jlAM4JHAmL9tTCf+6XN9to7G17HX8sKO/KTkQP4kbQiPlyzlIHLk+8dqMehDmRTmyGB6i5+1b9sgLNRtg== 9 | dependencies: 10 | "@release-notes/node" "^0.3.0" 11 | 12 | "@release-notes/cli@^0.3.0": 13 | version "0.3.0" 14 | resolved "https://registry.yarnpkg.com/@release-notes/cli/-/cli-0.3.0.tgz#ace2c434273420ecb32b3cfc56880a0782792be3" 15 | integrity sha512-LDvKdyW7X2Luxlk6MFcIOfWQCTpaXGtOg/0WfI9oK523nJ0Jv0cbC36nR3CPHifZBZ6waREt4cJea7o+rOmZlg== 16 | dependencies: 17 | "@release-notes/changelog-parser" "^0.1.2" 18 | "@release-notes/node" "^0.3.0" 19 | request "^2.83.0" 20 | yargs "^10.0.3" 21 | 22 | "@release-notes/node@^0.3.0": 23 | version "0.3.0" 24 | resolved "https://registry.yarnpkg.com/@release-notes/node/-/node-0.3.0.tgz#7c833c9916ac3ae414e46c9bd983e0c42b867fab" 25 | integrity sha1-fIM8mRasOuQU5Gyb2YPgxCuGf6s= 26 | dependencies: 27 | "@release-notes/schema" "^0.2.0" 28 | ajv "^5.5.2" 29 | js-yaml "^3.10.0" 30 | 31 | "@release-notes/schema@^0.2.0": 32 | version "0.2.0" 33 | resolved "https://registry.yarnpkg.com/@release-notes/schema/-/schema-0.2.0.tgz#16b7f551f3f09397cec5b432a1e357334f986fe2" 34 | integrity sha512-E9GX7w9Xd2kflVxwdKSZf/n+7lSJt9Uyuv2wxl9oai35MzqMNRlk86t5NYoIat7zt43HUlQIauAw0JFukIEFlw== 35 | 36 | ajv@^5.5.2: 37 | version "5.5.2" 38 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" 39 | integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= 40 | dependencies: 41 | co "^4.6.0" 42 | fast-deep-equal "^1.0.0" 43 | fast-json-stable-stringify "^2.0.0" 44 | json-schema-traverse "^0.3.0" 45 | 46 | ajv@^6.5.5: 47 | version "6.12.3" 48 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" 49 | integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== 50 | dependencies: 51 | fast-deep-equal "^3.1.1" 52 | fast-json-stable-stringify "^2.0.0" 53 | json-schema-traverse "^0.4.1" 54 | uri-js "^4.2.2" 55 | 56 | ansi-regex@^2.0.0: 57 | version "2.1.1" 58 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 59 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 60 | 61 | ansi-regex@^3.0.0: 62 | version "3.0.0" 63 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 64 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 65 | 66 | ansi-styles@^2.2.1: 67 | version "2.2.1" 68 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 69 | integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= 70 | 71 | append-transform@^0.4.0: 72 | version "0.4.0" 73 | resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" 74 | integrity sha1-126/jKlNJ24keja61EpLdKthGZE= 75 | dependencies: 76 | default-require-extensions "^1.0.0" 77 | 78 | archy@^1.0.0: 79 | version "1.0.0" 80 | resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" 81 | integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= 82 | 83 | argparse@^1.0.7: 84 | version "1.0.10" 85 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 86 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 87 | dependencies: 88 | sprintf-js "~1.0.2" 89 | 90 | arr-diff@^2.0.0: 91 | version "2.0.0" 92 | resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" 93 | integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= 94 | dependencies: 95 | arr-flatten "^1.0.1" 96 | 97 | arr-diff@^4.0.0: 98 | version "4.0.0" 99 | resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" 100 | integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= 101 | 102 | arr-flatten@^1.0.1, arr-flatten@^1.1.0: 103 | version "1.1.0" 104 | resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" 105 | integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== 106 | 107 | arr-union@^3.1.0: 108 | version "3.1.0" 109 | resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" 110 | integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= 111 | 112 | array-unique@^0.2.1: 113 | version "0.2.1" 114 | resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" 115 | integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= 116 | 117 | array-unique@^0.3.2: 118 | version "0.3.2" 119 | resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" 120 | integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= 121 | 122 | arrify@^1.0.1: 123 | version "1.0.1" 124 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 125 | integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= 126 | 127 | asn1@~0.2.3: 128 | version "0.2.4" 129 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" 130 | integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== 131 | dependencies: 132 | safer-buffer "~2.1.0" 133 | 134 | assert-plus@1.0.0, assert-plus@^1.0.0: 135 | version "1.0.0" 136 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 137 | integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= 138 | 139 | assertion-error@^1.1.0: 140 | version "1.1.0" 141 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" 142 | integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== 143 | 144 | assign-symbols@^1.0.0: 145 | version "1.0.0" 146 | resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" 147 | integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= 148 | 149 | asynckit@^0.4.0: 150 | version "0.4.0" 151 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 152 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 153 | 154 | atob@^2.1.2: 155 | version "2.1.2" 156 | resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" 157 | integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== 158 | 159 | aws-sign2@~0.7.0: 160 | version "0.7.0" 161 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 162 | integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= 163 | 164 | aws4@^1.8.0: 165 | version "1.10.0" 166 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" 167 | integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== 168 | 169 | babel-code-frame@^6.26.0: 170 | version "6.26.0" 171 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" 172 | integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= 173 | dependencies: 174 | chalk "^1.1.3" 175 | esutils "^2.0.2" 176 | js-tokens "^3.0.2" 177 | 178 | babel-generator@^6.18.0: 179 | version "6.26.1" 180 | resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" 181 | integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== 182 | dependencies: 183 | babel-messages "^6.23.0" 184 | babel-runtime "^6.26.0" 185 | babel-types "^6.26.0" 186 | detect-indent "^4.0.0" 187 | jsesc "^1.3.0" 188 | lodash "^4.17.4" 189 | source-map "^0.5.7" 190 | trim-right "^1.0.1" 191 | 192 | babel-messages@^6.23.0: 193 | version "6.23.0" 194 | resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" 195 | integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= 196 | dependencies: 197 | babel-runtime "^6.22.0" 198 | 199 | babel-runtime@^6.22.0, babel-runtime@^6.26.0: 200 | version "6.26.0" 201 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" 202 | integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= 203 | dependencies: 204 | core-js "^2.4.0" 205 | regenerator-runtime "^0.11.0" 206 | 207 | babel-template@^6.16.0: 208 | version "6.26.0" 209 | resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" 210 | integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= 211 | dependencies: 212 | babel-runtime "^6.26.0" 213 | babel-traverse "^6.26.0" 214 | babel-types "^6.26.0" 215 | babylon "^6.18.0" 216 | lodash "^4.17.4" 217 | 218 | babel-traverse@^6.18.0, babel-traverse@^6.26.0: 219 | version "6.26.0" 220 | resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" 221 | integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= 222 | dependencies: 223 | babel-code-frame "^6.26.0" 224 | babel-messages "^6.23.0" 225 | babel-runtime "^6.26.0" 226 | babel-types "^6.26.0" 227 | babylon "^6.18.0" 228 | debug "^2.6.8" 229 | globals "^9.18.0" 230 | invariant "^2.2.2" 231 | lodash "^4.17.4" 232 | 233 | babel-types@^6.18.0, babel-types@^6.26.0: 234 | version "6.26.0" 235 | resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" 236 | integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= 237 | dependencies: 238 | babel-runtime "^6.26.0" 239 | esutils "^2.0.2" 240 | lodash "^4.17.4" 241 | to-fast-properties "^1.0.3" 242 | 243 | babylon@^6.18.0: 244 | version "6.18.0" 245 | resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" 246 | integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== 247 | 248 | balanced-match@^1.0.0: 249 | version "1.0.0" 250 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 251 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 252 | 253 | base@^0.11.1: 254 | version "0.11.2" 255 | resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" 256 | integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== 257 | dependencies: 258 | cache-base "^1.0.1" 259 | class-utils "^0.3.5" 260 | component-emitter "^1.2.1" 261 | define-property "^1.0.0" 262 | isobject "^3.0.1" 263 | mixin-deep "^1.2.0" 264 | pascalcase "^0.1.1" 265 | 266 | bcrypt-pbkdf@^1.0.0: 267 | version "1.0.2" 268 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 269 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= 270 | dependencies: 271 | tweetnacl "^0.14.3" 272 | 273 | bl@^2.2.0: 274 | version "2.2.1" 275 | resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5" 276 | integrity sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g== 277 | dependencies: 278 | readable-stream "^2.3.5" 279 | safe-buffer "^5.1.1" 280 | 281 | bluebird@3.5.1: 282 | version "3.5.1" 283 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" 284 | integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== 285 | 286 | brace-expansion@^1.1.7: 287 | version "1.1.11" 288 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 289 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 290 | dependencies: 291 | balanced-match "^1.0.0" 292 | concat-map "0.0.1" 293 | 294 | braces@^1.8.2: 295 | version "1.8.5" 296 | resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" 297 | integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= 298 | dependencies: 299 | expand-range "^1.8.1" 300 | preserve "^0.2.0" 301 | repeat-element "^1.1.2" 302 | 303 | braces@^2.3.1: 304 | version "2.3.2" 305 | resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" 306 | integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== 307 | dependencies: 308 | arr-flatten "^1.1.0" 309 | array-unique "^0.3.2" 310 | extend-shallow "^2.0.1" 311 | fill-range "^4.0.0" 312 | isobject "^3.0.1" 313 | repeat-element "^1.1.2" 314 | snapdragon "^0.8.1" 315 | snapdragon-node "^2.0.1" 316 | split-string "^3.0.2" 317 | to-regex "^3.0.1" 318 | 319 | browser-stdout@1.3.1: 320 | version "1.3.1" 321 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 322 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 323 | 324 | bson@^1.1.4: 325 | version "1.1.4" 326 | resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.4.tgz#f76870d799f15b854dffb7ee32f0a874797f7e89" 327 | integrity sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q== 328 | 329 | bson@~1.0.4: 330 | version "1.0.9" 331 | resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.9.tgz#12319f8323b1254739b7c6bef8d3e89ae05a2f57" 332 | integrity sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg== 333 | 334 | buffer-shims@~1.0.0: 335 | version "1.0.0" 336 | resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" 337 | integrity sha1-mXjOMXOIxkmth5MCjDR37wRKi1E= 338 | 339 | cache-base@^1.0.1: 340 | version "1.0.1" 341 | resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" 342 | integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== 343 | dependencies: 344 | collection-visit "^1.0.0" 345 | component-emitter "^1.2.1" 346 | get-value "^2.0.6" 347 | has-value "^1.0.0" 348 | isobject "^3.0.1" 349 | set-value "^2.0.0" 350 | to-object-path "^0.3.0" 351 | union-value "^1.0.0" 352 | unset-value "^1.0.0" 353 | 354 | caching-transform@^1.0.0: 355 | version "1.0.1" 356 | resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" 357 | integrity sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE= 358 | dependencies: 359 | md5-hex "^1.2.0" 360 | mkdirp "^0.5.1" 361 | write-file-atomic "^1.1.4" 362 | 363 | camelcase@^4.1.0: 364 | version "4.1.0" 365 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" 366 | integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= 367 | 368 | caseless@~0.12.0: 369 | version "0.12.0" 370 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 371 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 372 | 373 | chai@^4.2.0: 374 | version "4.2.0" 375 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" 376 | integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== 377 | dependencies: 378 | assertion-error "^1.1.0" 379 | check-error "^1.0.2" 380 | deep-eql "^3.0.1" 381 | get-func-name "^2.0.0" 382 | pathval "^1.1.0" 383 | type-detect "^4.0.5" 384 | 385 | chalk@^1.1.3: 386 | version "1.1.3" 387 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 388 | integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= 389 | dependencies: 390 | ansi-styles "^2.2.1" 391 | escape-string-regexp "^1.0.2" 392 | has-ansi "^2.0.0" 393 | strip-ansi "^3.0.0" 394 | supports-color "^2.0.0" 395 | 396 | check-error@^1.0.2: 397 | version "1.0.2" 398 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" 399 | integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= 400 | 401 | class-utils@^0.3.5: 402 | version "0.3.6" 403 | resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" 404 | integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== 405 | dependencies: 406 | arr-union "^3.1.0" 407 | define-property "^0.2.5" 408 | isobject "^3.0.0" 409 | static-extend "^0.1.1" 410 | 411 | cli@~1.0.0: 412 | version "1.0.1" 413 | resolved "https://registry.yarnpkg.com/cli/-/cli-1.0.1.tgz#22817534f24bfa4950c34d532d48ecbc621b8c14" 414 | integrity sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ= 415 | dependencies: 416 | exit "0.1.2" 417 | glob "^7.1.1" 418 | 419 | cliui@^4.0.0: 420 | version "4.1.0" 421 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" 422 | integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== 423 | dependencies: 424 | string-width "^2.1.1" 425 | strip-ansi "^4.0.0" 426 | wrap-ansi "^2.0.0" 427 | 428 | co@^4.6.0: 429 | version "4.6.0" 430 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" 431 | integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= 432 | 433 | code-point-at@^1.0.0: 434 | version "1.1.0" 435 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 436 | integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 437 | 438 | collection-visit@^1.0.0: 439 | version "1.0.0" 440 | resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" 441 | integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= 442 | dependencies: 443 | map-visit "^1.0.0" 444 | object-visit "^1.0.0" 445 | 446 | combined-stream@^1.0.6, combined-stream@~1.0.6: 447 | version "1.0.8" 448 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 449 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 450 | dependencies: 451 | delayed-stream "~1.0.0" 452 | 453 | commander@2.15.1: 454 | version "2.15.1" 455 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" 456 | integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== 457 | 458 | commondir@^1.0.1: 459 | version "1.0.1" 460 | resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" 461 | integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= 462 | 463 | component-emitter@^1.2.1: 464 | version "1.3.0" 465 | resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" 466 | integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== 467 | 468 | concat-map@0.0.1: 469 | version "0.0.1" 470 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 471 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 472 | 473 | console-browserify@1.1.x: 474 | version "1.1.0" 475 | resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" 476 | integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= 477 | dependencies: 478 | date-now "^0.1.4" 479 | 480 | convert-source-map@^1.5.1: 481 | version "1.7.0" 482 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" 483 | integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== 484 | dependencies: 485 | safe-buffer "~5.1.1" 486 | 487 | copy-descriptor@^0.1.0: 488 | version "0.1.1" 489 | resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" 490 | integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= 491 | 492 | core-js@^2.4.0: 493 | version "2.6.11" 494 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" 495 | integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== 496 | 497 | core-util-is@1.0.2, core-util-is@~1.0.0: 498 | version "1.0.2" 499 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 500 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 501 | 502 | coveralls@^3.1.0: 503 | version "3.1.0" 504 | resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" 505 | integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== 506 | dependencies: 507 | js-yaml "^3.13.1" 508 | lcov-parse "^1.0.0" 509 | log-driver "^1.2.7" 510 | minimist "^1.2.5" 511 | request "^2.88.2" 512 | 513 | cross-spawn@^4: 514 | version "4.0.2" 515 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" 516 | integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= 517 | dependencies: 518 | lru-cache "^4.0.1" 519 | which "^1.2.9" 520 | 521 | cross-spawn@^5.0.1: 522 | version "5.1.0" 523 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" 524 | integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= 525 | dependencies: 526 | lru-cache "^4.0.1" 527 | shebang-command "^1.2.0" 528 | which "^1.2.9" 529 | 530 | dashdash@^1.12.0: 531 | version "1.14.1" 532 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 533 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= 534 | dependencies: 535 | assert-plus "^1.0.0" 536 | 537 | date-now@^0.1.4: 538 | version "0.1.4" 539 | resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" 540 | integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= 541 | 542 | debug-log@^1.0.1: 543 | version "1.0.1" 544 | resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" 545 | integrity sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8= 546 | 547 | debug@3.1.0: 548 | version "3.1.0" 549 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 550 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== 551 | dependencies: 552 | ms "2.0.0" 553 | 554 | debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: 555 | version "2.6.9" 556 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 557 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 558 | dependencies: 559 | ms "2.0.0" 560 | 561 | debug@^3.1.0: 562 | version "3.2.6" 563 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" 564 | integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== 565 | dependencies: 566 | ms "^2.1.1" 567 | 568 | decamelize@^1.1.1: 569 | version "1.2.0" 570 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 571 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 572 | 573 | decode-uri-component@^0.2.0: 574 | version "0.2.2" 575 | resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" 576 | integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== 577 | 578 | deep-eql@^3.0.1: 579 | version "3.0.1" 580 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" 581 | integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== 582 | dependencies: 583 | type-detect "^4.0.0" 584 | 585 | default-require-extensions@^1.0.0: 586 | version "1.0.0" 587 | resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" 588 | integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg= 589 | dependencies: 590 | strip-bom "^2.0.0" 591 | 592 | define-property@^0.2.5: 593 | version "0.2.5" 594 | resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" 595 | integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= 596 | dependencies: 597 | is-descriptor "^0.1.0" 598 | 599 | define-property@^1.0.0: 600 | version "1.0.0" 601 | resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" 602 | integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= 603 | dependencies: 604 | is-descriptor "^1.0.0" 605 | 606 | define-property@^2.0.2: 607 | version "2.0.2" 608 | resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" 609 | integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== 610 | dependencies: 611 | is-descriptor "^1.0.2" 612 | isobject "^3.0.1" 613 | 614 | delayed-stream@~1.0.0: 615 | version "1.0.0" 616 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 617 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 618 | 619 | denque@^1.4.1: 620 | version "1.4.1" 621 | resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" 622 | integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== 623 | 624 | detect-indent@^4.0.0: 625 | version "4.0.0" 626 | resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" 627 | integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= 628 | dependencies: 629 | repeating "^2.0.0" 630 | 631 | diff@3.5.0: 632 | version "3.5.0" 633 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 634 | integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== 635 | 636 | dom-serializer@0: 637 | version "0.2.2" 638 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" 639 | integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== 640 | dependencies: 641 | domelementtype "^2.0.1" 642 | entities "^2.0.0" 643 | 644 | domelementtype@1: 645 | version "1.3.1" 646 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" 647 | integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== 648 | 649 | domelementtype@^2.0.1: 650 | version "2.0.1" 651 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" 652 | integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== 653 | 654 | domhandler@2.3: 655 | version "2.3.0" 656 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" 657 | integrity sha1-LeWaCCLVAn+r/28DLCsloqir5zg= 658 | dependencies: 659 | domelementtype "1" 660 | 661 | domutils@1.5: 662 | version "1.5.1" 663 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" 664 | integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= 665 | dependencies: 666 | dom-serializer "0" 667 | domelementtype "1" 668 | 669 | ecc-jsbn@~0.1.1: 670 | version "0.1.2" 671 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 672 | integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= 673 | dependencies: 674 | jsbn "~0.1.0" 675 | safer-buffer "^2.1.0" 676 | 677 | entities@1.0: 678 | version "1.0.0" 679 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" 680 | integrity sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY= 681 | 682 | entities@^2.0.0: 683 | version "2.0.3" 684 | resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" 685 | integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== 686 | 687 | error-ex@^1.2.0: 688 | version "1.3.2" 689 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 690 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 691 | dependencies: 692 | is-arrayish "^0.2.1" 693 | 694 | es6-promise@3.2.1: 695 | version "3.2.1" 696 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4" 697 | integrity sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q= 698 | 699 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: 700 | version "1.0.5" 701 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 702 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 703 | 704 | esprima@^4.0.0: 705 | version "4.0.1" 706 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 707 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 708 | 709 | esutils@^2.0.2: 710 | version "2.0.3" 711 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 712 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 713 | 714 | execa@^0.7.0: 715 | version "0.7.0" 716 | resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" 717 | integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= 718 | dependencies: 719 | cross-spawn "^5.0.1" 720 | get-stream "^3.0.0" 721 | is-stream "^1.1.0" 722 | npm-run-path "^2.0.0" 723 | p-finally "^1.0.0" 724 | signal-exit "^3.0.0" 725 | strip-eof "^1.0.0" 726 | 727 | exit@0.1.2, exit@0.1.x: 728 | version "0.1.2" 729 | resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" 730 | integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= 731 | 732 | expand-brackets@^0.1.4: 733 | version "0.1.5" 734 | resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" 735 | integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= 736 | dependencies: 737 | is-posix-bracket "^0.1.0" 738 | 739 | expand-brackets@^2.1.4: 740 | version "2.1.4" 741 | resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" 742 | integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= 743 | dependencies: 744 | debug "^2.3.3" 745 | define-property "^0.2.5" 746 | extend-shallow "^2.0.1" 747 | posix-character-classes "^0.1.0" 748 | regex-not "^1.0.0" 749 | snapdragon "^0.8.1" 750 | to-regex "^3.0.1" 751 | 752 | expand-range@^1.8.1: 753 | version "1.8.2" 754 | resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" 755 | integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= 756 | dependencies: 757 | fill-range "^2.1.0" 758 | 759 | extend-shallow@^2.0.1: 760 | version "2.0.1" 761 | resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" 762 | integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= 763 | dependencies: 764 | is-extendable "^0.1.0" 765 | 766 | extend-shallow@^3.0.0, extend-shallow@^3.0.2: 767 | version "3.0.2" 768 | resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" 769 | integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= 770 | dependencies: 771 | assign-symbols "^1.0.0" 772 | is-extendable "^1.0.1" 773 | 774 | extend@~3.0.2: 775 | version "3.0.2" 776 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 777 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 778 | 779 | extglob@^0.3.1: 780 | version "0.3.2" 781 | resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" 782 | integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= 783 | dependencies: 784 | is-extglob "^1.0.0" 785 | 786 | extglob@^2.0.4: 787 | version "2.0.4" 788 | resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" 789 | integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== 790 | dependencies: 791 | array-unique "^0.3.2" 792 | define-property "^1.0.0" 793 | expand-brackets "^2.1.4" 794 | extend-shallow "^2.0.1" 795 | fragment-cache "^0.2.1" 796 | regex-not "^1.0.0" 797 | snapdragon "^0.8.1" 798 | to-regex "^3.0.1" 799 | 800 | extsprintf@1.3.0: 801 | version "1.3.0" 802 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 803 | integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= 804 | 805 | extsprintf@^1.2.0: 806 | version "1.4.0" 807 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 808 | integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 809 | 810 | fast-deep-equal@^1.0.0: 811 | version "1.1.0" 812 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" 813 | integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= 814 | 815 | fast-deep-equal@^3.1.1: 816 | version "3.1.3" 817 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 818 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 819 | 820 | fast-json-stable-stringify@^2.0.0: 821 | version "2.1.0" 822 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 823 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 824 | 825 | filename-regex@^2.0.0: 826 | version "2.0.1" 827 | resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" 828 | integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= 829 | 830 | fill-range@^2.1.0: 831 | version "2.2.4" 832 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" 833 | integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== 834 | dependencies: 835 | is-number "^2.1.0" 836 | isobject "^2.0.0" 837 | randomatic "^3.0.0" 838 | repeat-element "^1.1.2" 839 | repeat-string "^1.5.2" 840 | 841 | fill-range@^4.0.0: 842 | version "4.0.0" 843 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" 844 | integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= 845 | dependencies: 846 | extend-shallow "^2.0.1" 847 | is-number "^3.0.0" 848 | repeat-string "^1.6.1" 849 | to-regex-range "^2.1.0" 850 | 851 | find-cache-dir@^0.1.1: 852 | version "0.1.1" 853 | resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" 854 | integrity sha1-yN765XyKUqinhPnjHFfHQumToLk= 855 | dependencies: 856 | commondir "^1.0.1" 857 | mkdirp "^0.5.1" 858 | pkg-dir "^1.0.0" 859 | 860 | find-up@^1.0.0: 861 | version "1.1.2" 862 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" 863 | integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= 864 | dependencies: 865 | path-exists "^2.0.0" 866 | pinkie-promise "^2.0.0" 867 | 868 | find-up@^2.1.0: 869 | version "2.1.0" 870 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" 871 | integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= 872 | dependencies: 873 | locate-path "^2.0.0" 874 | 875 | for-in@^1.0.1, for-in@^1.0.2: 876 | version "1.0.2" 877 | resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" 878 | integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= 879 | 880 | for-own@^0.1.4: 881 | version "0.1.5" 882 | resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" 883 | integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= 884 | dependencies: 885 | for-in "^1.0.1" 886 | 887 | foreground-child@^1.5.3, foreground-child@^1.5.6: 888 | version "1.5.6" 889 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" 890 | integrity sha1-T9ca0t/elnibmApcCilZN8svXOk= 891 | dependencies: 892 | cross-spawn "^4" 893 | signal-exit "^3.0.0" 894 | 895 | forever-agent@~0.6.1: 896 | version "0.6.1" 897 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 898 | integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= 899 | 900 | form-data@~2.3.2: 901 | version "2.3.3" 902 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 903 | integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== 904 | dependencies: 905 | asynckit "^0.4.0" 906 | combined-stream "^1.0.6" 907 | mime-types "^2.1.12" 908 | 909 | fragment-cache@^0.2.1: 910 | version "0.2.1" 911 | resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" 912 | integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= 913 | dependencies: 914 | map-cache "^0.2.2" 915 | 916 | fs.realpath@^1.0.0: 917 | version "1.0.0" 918 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 919 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 920 | 921 | get-caller-file@^1.0.1: 922 | version "1.0.3" 923 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" 924 | integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== 925 | 926 | get-func-name@^2.0.0: 927 | version "2.0.2" 928 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" 929 | integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== 930 | 931 | get-stream@^3.0.0: 932 | version "3.0.0" 933 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 934 | integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= 935 | 936 | get-value@^2.0.3, get-value@^2.0.6: 937 | version "2.0.6" 938 | resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" 939 | integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= 940 | 941 | getpass@^0.1.1: 942 | version "0.1.7" 943 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 944 | integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= 945 | dependencies: 946 | assert-plus "^1.0.0" 947 | 948 | glob-base@^0.3.0: 949 | version "0.3.0" 950 | resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" 951 | integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= 952 | dependencies: 953 | glob-parent "^2.0.0" 954 | is-glob "^2.0.0" 955 | 956 | glob-parent@^2.0.0: 957 | version "2.0.0" 958 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" 959 | integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= 960 | dependencies: 961 | is-glob "^2.0.0" 962 | 963 | glob@7.1.2: 964 | version "7.1.2" 965 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 966 | integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== 967 | dependencies: 968 | fs.realpath "^1.0.0" 969 | inflight "^1.0.4" 970 | inherits "2" 971 | minimatch "^3.0.4" 972 | once "^1.3.0" 973 | path-is-absolute "^1.0.0" 974 | 975 | glob@^7.0.6, glob@^7.1.1, glob@^7.1.3: 976 | version "7.1.6" 977 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 978 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 979 | dependencies: 980 | fs.realpath "^1.0.0" 981 | inflight "^1.0.4" 982 | inherits "2" 983 | minimatch "^3.0.4" 984 | once "^1.3.0" 985 | path-is-absolute "^1.0.0" 986 | 987 | globals@^9.18.0: 988 | version "9.18.0" 989 | resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" 990 | integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== 991 | 992 | graceful-fs@^4.1.11, graceful-fs@^4.1.2: 993 | version "4.2.4" 994 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" 995 | integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== 996 | 997 | growl@1.10.5: 998 | version "1.10.5" 999 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 1000 | integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== 1001 | 1002 | handlebars@^4.0.3: 1003 | version "4.7.7" 1004 | resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" 1005 | integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== 1006 | dependencies: 1007 | minimist "^1.2.5" 1008 | neo-async "^2.6.0" 1009 | source-map "^0.6.1" 1010 | wordwrap "^1.0.0" 1011 | optionalDependencies: 1012 | uglify-js "^3.1.4" 1013 | 1014 | har-schema@^2.0.0: 1015 | version "2.0.0" 1016 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 1017 | integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= 1018 | 1019 | har-validator@~5.1.3: 1020 | version "5.1.3" 1021 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" 1022 | integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== 1023 | dependencies: 1024 | ajv "^6.5.5" 1025 | har-schema "^2.0.0" 1026 | 1027 | has-ansi@^2.0.0: 1028 | version "2.0.0" 1029 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 1030 | integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= 1031 | dependencies: 1032 | ansi-regex "^2.0.0" 1033 | 1034 | has-flag@^1.0.0: 1035 | version "1.0.0" 1036 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 1037 | integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= 1038 | 1039 | has-flag@^3.0.0: 1040 | version "3.0.0" 1041 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 1042 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 1043 | 1044 | has-value@^0.3.1: 1045 | version "0.3.1" 1046 | resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" 1047 | integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= 1048 | dependencies: 1049 | get-value "^2.0.3" 1050 | has-values "^0.1.4" 1051 | isobject "^2.0.0" 1052 | 1053 | has-value@^1.0.0: 1054 | version "1.0.0" 1055 | resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" 1056 | integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= 1057 | dependencies: 1058 | get-value "^2.0.6" 1059 | has-values "^1.0.0" 1060 | isobject "^3.0.0" 1061 | 1062 | has-values@^0.1.4: 1063 | version "0.1.4" 1064 | resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" 1065 | integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= 1066 | 1067 | has-values@^1.0.0: 1068 | version "1.0.0" 1069 | resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" 1070 | integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= 1071 | dependencies: 1072 | is-number "^3.0.0" 1073 | kind-of "^4.0.0" 1074 | 1075 | he@1.1.1: 1076 | version "1.1.1" 1077 | resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" 1078 | integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= 1079 | 1080 | hosted-git-info@^2.1.4: 1081 | version "2.8.9" 1082 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" 1083 | integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== 1084 | 1085 | htmlparser2@3.8.x: 1086 | version "3.8.3" 1087 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" 1088 | integrity sha1-mWwosZFRaovoZQGn15dX5ccMEGg= 1089 | dependencies: 1090 | domelementtype "1" 1091 | domhandler "2.3" 1092 | domutils "1.5" 1093 | entities "1.0" 1094 | readable-stream "1.1" 1095 | 1096 | http-signature@~1.2.0: 1097 | version "1.2.0" 1098 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 1099 | integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= 1100 | dependencies: 1101 | assert-plus "^1.0.0" 1102 | jsprim "^1.2.2" 1103 | sshpk "^1.7.0" 1104 | 1105 | imurmurhash@^0.1.4: 1106 | version "0.1.4" 1107 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 1108 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 1109 | 1110 | inflight@^1.0.4: 1111 | version "1.0.6" 1112 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 1113 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 1114 | dependencies: 1115 | once "^1.3.0" 1116 | wrappy "1" 1117 | 1118 | inherits@2, inherits@~2.0.1, inherits@~2.0.3: 1119 | version "2.0.4" 1120 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 1121 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 1122 | 1123 | invariant@^2.2.2: 1124 | version "2.2.4" 1125 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" 1126 | integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== 1127 | dependencies: 1128 | loose-envify "^1.0.0" 1129 | 1130 | invert-kv@^1.0.0: 1131 | version "1.0.0" 1132 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" 1133 | integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= 1134 | 1135 | is-accessor-descriptor@^0.1.6: 1136 | version "0.1.6" 1137 | resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" 1138 | integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= 1139 | dependencies: 1140 | kind-of "^3.0.2" 1141 | 1142 | is-accessor-descriptor@^1.0.0: 1143 | version "1.0.0" 1144 | resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" 1145 | integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== 1146 | dependencies: 1147 | kind-of "^6.0.0" 1148 | 1149 | is-arrayish@^0.2.1: 1150 | version "0.2.1" 1151 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 1152 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 1153 | 1154 | is-buffer@^1.1.5: 1155 | version "1.1.6" 1156 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 1157 | integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== 1158 | 1159 | is-data-descriptor@^0.1.4: 1160 | version "0.1.4" 1161 | resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" 1162 | integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= 1163 | dependencies: 1164 | kind-of "^3.0.2" 1165 | 1166 | is-data-descriptor@^1.0.0: 1167 | version "1.0.0" 1168 | resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" 1169 | integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== 1170 | dependencies: 1171 | kind-of "^6.0.0" 1172 | 1173 | is-descriptor@^0.1.0: 1174 | version "0.1.6" 1175 | resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" 1176 | integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== 1177 | dependencies: 1178 | is-accessor-descriptor "^0.1.6" 1179 | is-data-descriptor "^0.1.4" 1180 | kind-of "^5.0.0" 1181 | 1182 | is-descriptor@^1.0.0, is-descriptor@^1.0.2: 1183 | version "1.0.2" 1184 | resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" 1185 | integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== 1186 | dependencies: 1187 | is-accessor-descriptor "^1.0.0" 1188 | is-data-descriptor "^1.0.0" 1189 | kind-of "^6.0.2" 1190 | 1191 | is-dotfile@^1.0.0: 1192 | version "1.0.3" 1193 | resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" 1194 | integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= 1195 | 1196 | is-equal-shallow@^0.1.3: 1197 | version "0.1.3" 1198 | resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" 1199 | integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= 1200 | dependencies: 1201 | is-primitive "^2.0.0" 1202 | 1203 | is-extendable@^0.1.0, is-extendable@^0.1.1: 1204 | version "0.1.1" 1205 | resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" 1206 | integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= 1207 | 1208 | is-extendable@^1.0.1: 1209 | version "1.0.1" 1210 | resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" 1211 | integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== 1212 | dependencies: 1213 | is-plain-object "^2.0.4" 1214 | 1215 | is-extglob@^1.0.0: 1216 | version "1.0.0" 1217 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" 1218 | integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= 1219 | 1220 | is-finite@^1.0.0: 1221 | version "1.1.0" 1222 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" 1223 | integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== 1224 | 1225 | is-fullwidth-code-point@^1.0.0: 1226 | version "1.0.0" 1227 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 1228 | integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 1229 | dependencies: 1230 | number-is-nan "^1.0.0" 1231 | 1232 | is-fullwidth-code-point@^2.0.0: 1233 | version "2.0.0" 1234 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 1235 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 1236 | 1237 | is-glob@^2.0.0, is-glob@^2.0.1: 1238 | version "2.0.1" 1239 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" 1240 | integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= 1241 | dependencies: 1242 | is-extglob "^1.0.0" 1243 | 1244 | is-number@^2.1.0: 1245 | version "2.1.0" 1246 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" 1247 | integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= 1248 | dependencies: 1249 | kind-of "^3.0.2" 1250 | 1251 | is-number@^3.0.0: 1252 | version "3.0.0" 1253 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" 1254 | integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= 1255 | dependencies: 1256 | kind-of "^3.0.2" 1257 | 1258 | is-number@^4.0.0: 1259 | version "4.0.0" 1260 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" 1261 | integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== 1262 | 1263 | is-plain-object@^2.0.3, is-plain-object@^2.0.4: 1264 | version "2.0.4" 1265 | resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" 1266 | integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== 1267 | dependencies: 1268 | isobject "^3.0.1" 1269 | 1270 | is-posix-bracket@^0.1.0: 1271 | version "0.1.1" 1272 | resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" 1273 | integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= 1274 | 1275 | is-primitive@^2.0.0: 1276 | version "2.0.0" 1277 | resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" 1278 | integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= 1279 | 1280 | is-stream@^1.1.0: 1281 | version "1.1.0" 1282 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 1283 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 1284 | 1285 | is-typedarray@~1.0.0: 1286 | version "1.0.0" 1287 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 1288 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 1289 | 1290 | is-utf8@^0.2.0: 1291 | version "0.2.1" 1292 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 1293 | integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= 1294 | 1295 | is-windows@^1.0.2: 1296 | version "1.0.2" 1297 | resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" 1298 | integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== 1299 | 1300 | isarray@0.0.1: 1301 | version "0.0.1" 1302 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 1303 | integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= 1304 | 1305 | isarray@1.0.0, isarray@~1.0.0: 1306 | version "1.0.0" 1307 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 1308 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 1309 | 1310 | isexe@^2.0.0: 1311 | version "2.0.0" 1312 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 1313 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 1314 | 1315 | isobject@^2.0.0: 1316 | version "2.1.0" 1317 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" 1318 | integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= 1319 | dependencies: 1320 | isarray "1.0.0" 1321 | 1322 | isobject@^3.0.0, isobject@^3.0.1: 1323 | version "3.0.1" 1324 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" 1325 | integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= 1326 | 1327 | isstream@~0.1.2: 1328 | version "0.1.2" 1329 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 1330 | integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= 1331 | 1332 | istanbul-lib-coverage@^1.1.2, istanbul-lib-coverage@^1.2.1: 1333 | version "1.2.1" 1334 | resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" 1335 | integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ== 1336 | 1337 | istanbul-lib-hook@^1.1.0: 1338 | version "1.2.2" 1339 | resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86" 1340 | integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw== 1341 | dependencies: 1342 | append-transform "^0.4.0" 1343 | 1344 | istanbul-lib-instrument@^1.10.0: 1345 | version "1.10.2" 1346 | resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca" 1347 | integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A== 1348 | dependencies: 1349 | babel-generator "^6.18.0" 1350 | babel-template "^6.16.0" 1351 | babel-traverse "^6.18.0" 1352 | babel-types "^6.18.0" 1353 | babylon "^6.18.0" 1354 | istanbul-lib-coverage "^1.2.1" 1355 | semver "^5.3.0" 1356 | 1357 | istanbul-lib-report@^1.1.3: 1358 | version "1.1.5" 1359 | resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c" 1360 | integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw== 1361 | dependencies: 1362 | istanbul-lib-coverage "^1.2.1" 1363 | mkdirp "^0.5.1" 1364 | path-parse "^1.0.5" 1365 | supports-color "^3.1.2" 1366 | 1367 | istanbul-lib-source-maps@^1.2.3: 1368 | version "1.2.6" 1369 | resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f" 1370 | integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg== 1371 | dependencies: 1372 | debug "^3.1.0" 1373 | istanbul-lib-coverage "^1.2.1" 1374 | mkdirp "^0.5.1" 1375 | rimraf "^2.6.1" 1376 | source-map "^0.5.3" 1377 | 1378 | istanbul-reports@^1.4.0: 1379 | version "1.5.1" 1380 | resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a" 1381 | integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw== 1382 | dependencies: 1383 | handlebars "^4.0.3" 1384 | 1385 | "js-tokens@^3.0.0 || ^4.0.0": 1386 | version "4.0.0" 1387 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 1388 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 1389 | 1390 | js-tokens@^3.0.2: 1391 | version "3.0.2" 1392 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 1393 | integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= 1394 | 1395 | js-yaml@^3.10.0, js-yaml@^3.13.1: 1396 | version "3.14.0" 1397 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" 1398 | integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== 1399 | dependencies: 1400 | argparse "^1.0.7" 1401 | esprima "^4.0.0" 1402 | 1403 | jsbn@~0.1.0: 1404 | version "0.1.1" 1405 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 1406 | integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= 1407 | 1408 | jsesc@^1.3.0: 1409 | version "1.3.0" 1410 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" 1411 | integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= 1412 | 1413 | jshint@^2.11.1: 1414 | version "2.11.1" 1415 | resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.11.1.tgz#28ec7d1cf7baaae5ce7bd37b9a70ed6cfd938570" 1416 | integrity sha512-WXWePB8ssAH3DlD05IoqolsY6arhbll/1+i2JkRPpihQAuiNaR/gSt8VKIcxpV5m6XChP0hCwESQUqpuQMA8Tg== 1417 | dependencies: 1418 | cli "~1.0.0" 1419 | console-browserify "1.1.x" 1420 | exit "0.1.x" 1421 | htmlparser2 "3.8.x" 1422 | lodash "~4.17.11" 1423 | minimatch "~3.0.2" 1424 | shelljs "0.3.x" 1425 | strip-json-comments "1.0.x" 1426 | 1427 | json-schema-traverse@^0.3.0: 1428 | version "0.3.1" 1429 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" 1430 | integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= 1431 | 1432 | json-schema-traverse@^0.4.1: 1433 | version "0.4.1" 1434 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 1435 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 1436 | 1437 | json-schema@0.2.3: 1438 | version "0.2.3" 1439 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 1440 | integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= 1441 | 1442 | json-stringify-safe@~5.0.1: 1443 | version "5.0.1" 1444 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 1445 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= 1446 | 1447 | jsprim@^1.2.2: 1448 | version "1.4.1" 1449 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 1450 | integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= 1451 | dependencies: 1452 | assert-plus "1.0.0" 1453 | extsprintf "1.3.0" 1454 | json-schema "0.2.3" 1455 | verror "1.10.0" 1456 | 1457 | kareem@2.3.1: 1458 | version "2.3.1" 1459 | resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.1.tgz#def12d9c941017fabfb00f873af95e9c99e1be87" 1460 | integrity sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw== 1461 | 1462 | kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: 1463 | version "3.2.2" 1464 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" 1465 | integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= 1466 | dependencies: 1467 | is-buffer "^1.1.5" 1468 | 1469 | kind-of@^4.0.0: 1470 | version "4.0.0" 1471 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" 1472 | integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= 1473 | dependencies: 1474 | is-buffer "^1.1.5" 1475 | 1476 | kind-of@^5.0.0: 1477 | version "5.1.0" 1478 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" 1479 | integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== 1480 | 1481 | kind-of@^6.0.0, kind-of@^6.0.2: 1482 | version "6.0.3" 1483 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 1484 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 1485 | 1486 | lcid@^1.0.0: 1487 | version "1.0.0" 1488 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" 1489 | integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= 1490 | dependencies: 1491 | invert-kv "^1.0.0" 1492 | 1493 | lcov-parse@^1.0.0: 1494 | version "1.0.0" 1495 | resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" 1496 | integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= 1497 | 1498 | load-json-file@^1.0.0: 1499 | version "1.1.0" 1500 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" 1501 | integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= 1502 | dependencies: 1503 | graceful-fs "^4.1.2" 1504 | parse-json "^2.2.0" 1505 | pify "^2.0.0" 1506 | pinkie-promise "^2.0.0" 1507 | strip-bom "^2.0.0" 1508 | 1509 | locate-path@^2.0.0: 1510 | version "2.0.0" 1511 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" 1512 | integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= 1513 | dependencies: 1514 | p-locate "^2.0.0" 1515 | path-exists "^3.0.0" 1516 | 1517 | lodash@^4.17.4, lodash@~4.17.11: 1518 | version "4.17.21" 1519 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 1520 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 1521 | 1522 | log-driver@^1.2.7: 1523 | version "1.2.7" 1524 | resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" 1525 | integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== 1526 | 1527 | loose-envify@^1.0.0: 1528 | version "1.4.0" 1529 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 1530 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 1531 | dependencies: 1532 | js-tokens "^3.0.0 || ^4.0.0" 1533 | 1534 | lru-cache@^4.0.1: 1535 | version "4.1.5" 1536 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" 1537 | integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== 1538 | dependencies: 1539 | pseudomap "^1.0.2" 1540 | yallist "^2.1.2" 1541 | 1542 | map-cache@^0.2.2: 1543 | version "0.2.2" 1544 | resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" 1545 | integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= 1546 | 1547 | map-visit@^1.0.0: 1548 | version "1.0.0" 1549 | resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" 1550 | integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= 1551 | dependencies: 1552 | object-visit "^1.0.0" 1553 | 1554 | math-random@^1.0.1: 1555 | version "1.0.4" 1556 | resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" 1557 | integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== 1558 | 1559 | md5-hex@^1.2.0: 1560 | version "1.3.0" 1561 | resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" 1562 | integrity sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ= 1563 | dependencies: 1564 | md5-o-matic "^0.1.1" 1565 | 1566 | md5-o-matic@^0.1.1: 1567 | version "0.1.1" 1568 | resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" 1569 | integrity sha1-givM1l4RfFFPqxdrJZRdVBAKA8M= 1570 | 1571 | mem@^1.1.0: 1572 | version "1.1.0" 1573 | resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" 1574 | integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= 1575 | dependencies: 1576 | mimic-fn "^1.0.0" 1577 | 1578 | memory-pager@^1.0.2: 1579 | version "1.5.0" 1580 | resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" 1581 | integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== 1582 | 1583 | merge-source-map@^1.1.0: 1584 | version "1.1.0" 1585 | resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" 1586 | integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== 1587 | dependencies: 1588 | source-map "^0.6.1" 1589 | 1590 | micromatch@^2.3.11: 1591 | version "2.3.11" 1592 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" 1593 | integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= 1594 | dependencies: 1595 | arr-diff "^2.0.0" 1596 | array-unique "^0.2.1" 1597 | braces "^1.8.2" 1598 | expand-brackets "^0.1.4" 1599 | extglob "^0.3.1" 1600 | filename-regex "^2.0.0" 1601 | is-extglob "^1.0.0" 1602 | is-glob "^2.0.1" 1603 | kind-of "^3.0.2" 1604 | normalize-path "^2.0.1" 1605 | object.omit "^2.0.0" 1606 | parse-glob "^3.0.4" 1607 | regex-cache "^0.4.2" 1608 | 1609 | micromatch@^3.1.10: 1610 | version "3.1.10" 1611 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" 1612 | integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== 1613 | dependencies: 1614 | arr-diff "^4.0.0" 1615 | array-unique "^0.3.2" 1616 | braces "^2.3.1" 1617 | define-property "^2.0.2" 1618 | extend-shallow "^3.0.2" 1619 | extglob "^2.0.4" 1620 | fragment-cache "^0.2.1" 1621 | kind-of "^6.0.2" 1622 | nanomatch "^1.2.9" 1623 | object.pick "^1.3.0" 1624 | regex-not "^1.0.0" 1625 | snapdragon "^0.8.1" 1626 | to-regex "^3.0.2" 1627 | 1628 | mime-db@1.44.0: 1629 | version "1.44.0" 1630 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" 1631 | integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== 1632 | 1633 | mime-types@^2.1.12, mime-types@~2.1.19: 1634 | version "2.1.27" 1635 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" 1636 | integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== 1637 | dependencies: 1638 | mime-db "1.44.0" 1639 | 1640 | mimic-fn@^1.0.0: 1641 | version "1.2.0" 1642 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" 1643 | integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== 1644 | 1645 | minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2: 1646 | version "3.0.4" 1647 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 1648 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 1649 | dependencies: 1650 | brace-expansion "^1.1.7" 1651 | 1652 | minimist@0.0.8: 1653 | version "0.0.8" 1654 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 1655 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= 1656 | 1657 | minimist@^1.2.5: 1658 | version "1.2.5" 1659 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 1660 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 1661 | 1662 | mixin-deep@^1.2.0: 1663 | version "1.3.2" 1664 | resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" 1665 | integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== 1666 | dependencies: 1667 | for-in "^1.0.2" 1668 | is-extendable "^1.0.1" 1669 | 1670 | mkdirp@0.5.1: 1671 | version "0.5.1" 1672 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 1673 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= 1674 | dependencies: 1675 | minimist "0.0.8" 1676 | 1677 | mkdirp@^0.5.0, mkdirp@^0.5.1: 1678 | version "0.5.5" 1679 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" 1680 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 1681 | dependencies: 1682 | minimist "^1.2.5" 1683 | 1684 | mocha-mongoose@^1.2.0: 1685 | version "1.2.0" 1686 | resolved "https://registry.yarnpkg.com/mocha-mongoose/-/mocha-mongoose-1.2.0.tgz#d07066262668864c304e348b1670bc52ba25cdf3" 1687 | integrity sha1-0HBmJiZohkwwTjSLFnC8UrolzfM= 1688 | 1689 | mocha@^5.2.0: 1690 | version "5.2.0" 1691 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" 1692 | integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== 1693 | dependencies: 1694 | browser-stdout "1.3.1" 1695 | commander "2.15.1" 1696 | debug "3.1.0" 1697 | diff "3.5.0" 1698 | escape-string-regexp "1.0.5" 1699 | glob "7.1.2" 1700 | growl "1.10.5" 1701 | he "1.1.1" 1702 | minimatch "3.0.4" 1703 | mkdirp "0.5.1" 1704 | supports-color "5.4.0" 1705 | 1706 | mongodb-core@2.1.20: 1707 | version "2.1.20" 1708 | resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.20.tgz#fece8dd76b59ee7d7f2d313b65322c160492d8f1" 1709 | integrity sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ== 1710 | dependencies: 1711 | bson "~1.0.4" 1712 | require_optional "~1.0.0" 1713 | 1714 | mongodb@3.5.9: 1715 | version "3.5.9" 1716 | resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.5.9.tgz#799b72be8110b7e71a882bb7ce0d84d05429f772" 1717 | integrity sha512-vXHBY1CsGYcEPoVWhwgxIBeWqP3dSu9RuRDsoLRPTITrcrgm1f0Ubu1xqF9ozMwv53agmEiZm0YGo+7WL3Nbug== 1718 | dependencies: 1719 | bl "^2.2.0" 1720 | bson "^1.1.4" 1721 | denque "^1.4.1" 1722 | require_optional "^1.0.1" 1723 | safe-buffer "^5.1.2" 1724 | optionalDependencies: 1725 | saslprep "^1.0.0" 1726 | 1727 | mongodb@^2.2.36: 1728 | version "2.2.36" 1729 | resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.36.tgz#1c573680b2849fb0f47acbba3dc5fa228de975f5" 1730 | integrity sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA== 1731 | dependencies: 1732 | es6-promise "3.2.1" 1733 | mongodb-core "2.1.20" 1734 | readable-stream "2.2.7" 1735 | 1736 | mongoose-legacy-pluralize@1.0.2: 1737 | version "1.0.2" 1738 | resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4" 1739 | integrity sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ== 1740 | 1741 | mongoose@^5.9.23: 1742 | version "5.9.23" 1743 | resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.9.23.tgz#cb16687fbd19082bbbf0b8fab4778e2e4d85e7b1" 1744 | integrity sha512-fMYlMRJz0T6Ax2K2P0jt+kxXd4qaRxyfZCha1YBMczmA2EBlT5SnBlcDyJ4YQa4/z+GoDh06uH090w7BfBcdWg== 1745 | dependencies: 1746 | bson "^1.1.4" 1747 | kareem "2.3.1" 1748 | mongodb "3.5.9" 1749 | mongoose-legacy-pluralize "1.0.2" 1750 | mpath "0.7.0" 1751 | mquery "3.2.2" 1752 | ms "2.1.2" 1753 | regexp-clone "1.0.0" 1754 | safe-buffer "5.2.1" 1755 | sift "7.0.1" 1756 | sliced "1.0.1" 1757 | 1758 | mpath@0.7.0: 1759 | version "0.7.0" 1760 | resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.7.0.tgz#20e8102e276b71709d6e07e9f8d4d0f641afbfb8" 1761 | integrity sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg== 1762 | 1763 | mquery@3.2.2: 1764 | version "3.2.2" 1765 | resolved "https://registry.yarnpkg.com/mquery/-/mquery-3.2.2.tgz#e1383a3951852ce23e37f619a9b350f1fb3664e7" 1766 | integrity sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q== 1767 | dependencies: 1768 | bluebird "3.5.1" 1769 | debug "3.1.0" 1770 | regexp-clone "^1.0.0" 1771 | safe-buffer "5.1.2" 1772 | sliced "1.0.1" 1773 | 1774 | ms@2.0.0: 1775 | version "2.0.0" 1776 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 1777 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 1778 | 1779 | ms@2.1.2, ms@^2.1.1: 1780 | version "2.1.2" 1781 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1782 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1783 | 1784 | nanomatch@^1.2.9: 1785 | version "1.2.13" 1786 | resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" 1787 | integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== 1788 | dependencies: 1789 | arr-diff "^4.0.0" 1790 | array-unique "^0.3.2" 1791 | define-property "^2.0.2" 1792 | extend-shallow "^3.0.2" 1793 | fragment-cache "^0.2.1" 1794 | is-windows "^1.0.2" 1795 | kind-of "^6.0.2" 1796 | object.pick "^1.3.0" 1797 | regex-not "^1.0.0" 1798 | snapdragon "^0.8.1" 1799 | to-regex "^3.0.1" 1800 | 1801 | neo-async@^2.6.0: 1802 | version "2.6.2" 1803 | resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" 1804 | integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== 1805 | 1806 | normalize-package-data@^2.3.2: 1807 | version "2.5.0" 1808 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 1809 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 1810 | dependencies: 1811 | hosted-git-info "^2.1.4" 1812 | resolve "^1.10.0" 1813 | semver "2 || 3 || 4 || 5" 1814 | validate-npm-package-license "^3.0.1" 1815 | 1816 | normalize-path@^2.0.1: 1817 | version "2.1.1" 1818 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" 1819 | integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= 1820 | dependencies: 1821 | remove-trailing-separator "^1.0.1" 1822 | 1823 | npm-run-path@^2.0.0: 1824 | version "2.0.2" 1825 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 1826 | integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= 1827 | dependencies: 1828 | path-key "^2.0.0" 1829 | 1830 | number-is-nan@^1.0.0: 1831 | version "1.0.1" 1832 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 1833 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 1834 | 1835 | nyc@^11.9.0: 1836 | version "11.9.0" 1837 | resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.9.0.tgz#4106e89e8fbe73623a1fc8b6ecb7abaa271ae1e4" 1838 | integrity sha512-w8OdJAhXL5izerzZMdqzYKMj/pgHJyY3qEPYBjLLxrhcVoHEY9pU5ENIiZyCgG9OR7x3VcUMoD40o6PtVpfR4g== 1839 | dependencies: 1840 | archy "^1.0.0" 1841 | arrify "^1.0.1" 1842 | caching-transform "^1.0.0" 1843 | convert-source-map "^1.5.1" 1844 | debug-log "^1.0.1" 1845 | default-require-extensions "^1.0.0" 1846 | find-cache-dir "^0.1.1" 1847 | find-up "^2.1.0" 1848 | foreground-child "^1.5.3" 1849 | glob "^7.0.6" 1850 | istanbul-lib-coverage "^1.1.2" 1851 | istanbul-lib-hook "^1.1.0" 1852 | istanbul-lib-instrument "^1.10.0" 1853 | istanbul-lib-report "^1.1.3" 1854 | istanbul-lib-source-maps "^1.2.3" 1855 | istanbul-reports "^1.4.0" 1856 | md5-hex "^1.2.0" 1857 | merge-source-map "^1.1.0" 1858 | micromatch "^3.1.10" 1859 | mkdirp "^0.5.0" 1860 | resolve-from "^2.0.0" 1861 | rimraf "^2.6.2" 1862 | signal-exit "^3.0.1" 1863 | spawn-wrap "^1.4.2" 1864 | test-exclude "^4.2.0" 1865 | yargs "11.1.0" 1866 | yargs-parser "^8.0.0" 1867 | 1868 | oauth-sign@~0.9.0: 1869 | version "0.9.0" 1870 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 1871 | integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== 1872 | 1873 | object-assign@^4.1.0: 1874 | version "4.1.1" 1875 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1876 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 1877 | 1878 | object-copy@^0.1.0: 1879 | version "0.1.0" 1880 | resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" 1881 | integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= 1882 | dependencies: 1883 | copy-descriptor "^0.1.0" 1884 | define-property "^0.2.5" 1885 | kind-of "^3.0.3" 1886 | 1887 | object-visit@^1.0.0: 1888 | version "1.0.1" 1889 | resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" 1890 | integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= 1891 | dependencies: 1892 | isobject "^3.0.0" 1893 | 1894 | object.omit@^2.0.0: 1895 | version "2.0.1" 1896 | resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" 1897 | integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= 1898 | dependencies: 1899 | for-own "^0.1.4" 1900 | is-extendable "^0.1.1" 1901 | 1902 | object.pick@^1.3.0: 1903 | version "1.3.0" 1904 | resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" 1905 | integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= 1906 | dependencies: 1907 | isobject "^3.0.1" 1908 | 1909 | once@^1.3.0: 1910 | version "1.4.0" 1911 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1912 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1913 | dependencies: 1914 | wrappy "1" 1915 | 1916 | os-homedir@^1.0.1: 1917 | version "1.0.2" 1918 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 1919 | integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= 1920 | 1921 | os-locale@^2.0.0: 1922 | version "2.1.0" 1923 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" 1924 | integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== 1925 | dependencies: 1926 | execa "^0.7.0" 1927 | lcid "^1.0.0" 1928 | mem "^1.1.0" 1929 | 1930 | p-finally@^1.0.0: 1931 | version "1.0.0" 1932 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 1933 | integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= 1934 | 1935 | p-limit@^1.1.0: 1936 | version "1.3.0" 1937 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" 1938 | integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== 1939 | dependencies: 1940 | p-try "^1.0.0" 1941 | 1942 | p-locate@^2.0.0: 1943 | version "2.0.0" 1944 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" 1945 | integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= 1946 | dependencies: 1947 | p-limit "^1.1.0" 1948 | 1949 | p-try@^1.0.0: 1950 | version "1.0.0" 1951 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" 1952 | integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= 1953 | 1954 | parse-glob@^3.0.4: 1955 | version "3.0.4" 1956 | resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" 1957 | integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= 1958 | dependencies: 1959 | glob-base "^0.3.0" 1960 | is-dotfile "^1.0.0" 1961 | is-extglob "^1.0.0" 1962 | is-glob "^2.0.0" 1963 | 1964 | parse-json@^2.2.0: 1965 | version "2.2.0" 1966 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 1967 | integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= 1968 | dependencies: 1969 | error-ex "^1.2.0" 1970 | 1971 | pascalcase@^0.1.1: 1972 | version "0.1.1" 1973 | resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" 1974 | integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= 1975 | 1976 | path-exists@^2.0.0: 1977 | version "2.1.0" 1978 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" 1979 | integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= 1980 | dependencies: 1981 | pinkie-promise "^2.0.0" 1982 | 1983 | path-exists@^3.0.0: 1984 | version "3.0.0" 1985 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 1986 | integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= 1987 | 1988 | path-is-absolute@^1.0.0: 1989 | version "1.0.1" 1990 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1991 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1992 | 1993 | path-key@^2.0.0: 1994 | version "2.0.1" 1995 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 1996 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 1997 | 1998 | path-parse@^1.0.5, path-parse@^1.0.6: 1999 | version "1.0.7" 2000 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 2001 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 2002 | 2003 | path-type@^1.0.0: 2004 | version "1.1.0" 2005 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" 2006 | integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= 2007 | dependencies: 2008 | graceful-fs "^4.1.2" 2009 | pify "^2.0.0" 2010 | pinkie-promise "^2.0.0" 2011 | 2012 | pathval@^1.1.0: 2013 | version "1.1.1" 2014 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" 2015 | integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== 2016 | 2017 | performance-now@^2.1.0: 2018 | version "2.1.0" 2019 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 2020 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= 2021 | 2022 | pify@^2.0.0: 2023 | version "2.3.0" 2024 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 2025 | integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= 2026 | 2027 | pinkie-promise@^2.0.0: 2028 | version "2.0.1" 2029 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 2030 | integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= 2031 | dependencies: 2032 | pinkie "^2.0.0" 2033 | 2034 | pinkie@^2.0.0: 2035 | version "2.0.4" 2036 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 2037 | integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= 2038 | 2039 | pkg-dir@^1.0.0: 2040 | version "1.0.0" 2041 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" 2042 | integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q= 2043 | dependencies: 2044 | find-up "^1.0.0" 2045 | 2046 | posix-character-classes@^0.1.0: 2047 | version "0.1.1" 2048 | resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" 2049 | integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= 2050 | 2051 | preserve@^0.2.0: 2052 | version "0.2.0" 2053 | resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" 2054 | integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= 2055 | 2056 | process-nextick-args@~1.0.6: 2057 | version "1.0.7" 2058 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 2059 | integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= 2060 | 2061 | process-nextick-args@~2.0.0: 2062 | version "2.0.1" 2063 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 2064 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 2065 | 2066 | pseudomap@^1.0.2: 2067 | version "1.0.2" 2068 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 2069 | integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= 2070 | 2071 | psl@^1.1.28: 2072 | version "1.8.0" 2073 | resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" 2074 | integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== 2075 | 2076 | punycode@^2.1.0, punycode@^2.1.1: 2077 | version "2.1.1" 2078 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 2079 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 2080 | 2081 | qs@~6.5.2: 2082 | version "6.5.3" 2083 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" 2084 | integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== 2085 | 2086 | randomatic@^3.0.0: 2087 | version "3.1.1" 2088 | resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" 2089 | integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== 2090 | dependencies: 2091 | is-number "^4.0.0" 2092 | kind-of "^6.0.0" 2093 | math-random "^1.0.1" 2094 | 2095 | read-pkg-up@^1.0.1: 2096 | version "1.0.1" 2097 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" 2098 | integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= 2099 | dependencies: 2100 | find-up "^1.0.0" 2101 | read-pkg "^1.0.0" 2102 | 2103 | read-pkg@^1.0.0: 2104 | version "1.1.0" 2105 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" 2106 | integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= 2107 | dependencies: 2108 | load-json-file "^1.0.0" 2109 | normalize-package-data "^2.3.2" 2110 | path-type "^1.0.0" 2111 | 2112 | readable-stream@1.1: 2113 | version "1.1.13" 2114 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" 2115 | integrity sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4= 2116 | dependencies: 2117 | core-util-is "~1.0.0" 2118 | inherits "~2.0.1" 2119 | isarray "0.0.1" 2120 | string_decoder "~0.10.x" 2121 | 2122 | readable-stream@2.2.7: 2123 | version "2.2.7" 2124 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1" 2125 | integrity sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE= 2126 | dependencies: 2127 | buffer-shims "~1.0.0" 2128 | core-util-is "~1.0.0" 2129 | inherits "~2.0.1" 2130 | isarray "~1.0.0" 2131 | process-nextick-args "~1.0.6" 2132 | string_decoder "~1.0.0" 2133 | util-deprecate "~1.0.1" 2134 | 2135 | readable-stream@^2.3.5: 2136 | version "2.3.7" 2137 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" 2138 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 2139 | dependencies: 2140 | core-util-is "~1.0.0" 2141 | inherits "~2.0.3" 2142 | isarray "~1.0.0" 2143 | process-nextick-args "~2.0.0" 2144 | safe-buffer "~5.1.1" 2145 | string_decoder "~1.1.1" 2146 | util-deprecate "~1.0.1" 2147 | 2148 | regenerator-runtime@^0.11.0: 2149 | version "0.11.1" 2150 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" 2151 | integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== 2152 | 2153 | regex-cache@^0.4.2: 2154 | version "0.4.4" 2155 | resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" 2156 | integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== 2157 | dependencies: 2158 | is-equal-shallow "^0.1.3" 2159 | 2160 | regex-not@^1.0.0, regex-not@^1.0.2: 2161 | version "1.0.2" 2162 | resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" 2163 | integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== 2164 | dependencies: 2165 | extend-shallow "^3.0.2" 2166 | safe-regex "^1.1.0" 2167 | 2168 | regexp-clone@1.0.0, regexp-clone@^1.0.0: 2169 | version "1.0.0" 2170 | resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-1.0.0.tgz#222db967623277056260b992626354a04ce9bf63" 2171 | integrity sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw== 2172 | 2173 | remove-trailing-separator@^1.0.1: 2174 | version "1.1.0" 2175 | resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" 2176 | integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= 2177 | 2178 | repeat-element@^1.1.2: 2179 | version "1.1.3" 2180 | resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" 2181 | integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== 2182 | 2183 | repeat-string@^1.5.2, repeat-string@^1.6.1: 2184 | version "1.6.1" 2185 | resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 2186 | integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= 2187 | 2188 | repeating@^2.0.0: 2189 | version "2.0.1" 2190 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 2191 | integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= 2192 | dependencies: 2193 | is-finite "^1.0.0" 2194 | 2195 | request@^2.83.0, request@^2.88.2: 2196 | version "2.88.2" 2197 | resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" 2198 | integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== 2199 | dependencies: 2200 | aws-sign2 "~0.7.0" 2201 | aws4 "^1.8.0" 2202 | caseless "~0.12.0" 2203 | combined-stream "~1.0.6" 2204 | extend "~3.0.2" 2205 | forever-agent "~0.6.1" 2206 | form-data "~2.3.2" 2207 | har-validator "~5.1.3" 2208 | http-signature "~1.2.0" 2209 | is-typedarray "~1.0.0" 2210 | isstream "~0.1.2" 2211 | json-stringify-safe "~5.0.1" 2212 | mime-types "~2.1.19" 2213 | oauth-sign "~0.9.0" 2214 | performance-now "^2.1.0" 2215 | qs "~6.5.2" 2216 | safe-buffer "^5.1.2" 2217 | tough-cookie "~2.5.0" 2218 | tunnel-agent "^0.6.0" 2219 | uuid "^3.3.2" 2220 | 2221 | require-directory@^2.1.1: 2222 | version "2.1.1" 2223 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 2224 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= 2225 | 2226 | require-main-filename@^1.0.1: 2227 | version "1.0.1" 2228 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" 2229 | integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= 2230 | 2231 | require_optional@^1.0.1, require_optional@~1.0.0: 2232 | version "1.0.1" 2233 | resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" 2234 | integrity sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g== 2235 | dependencies: 2236 | resolve-from "^2.0.0" 2237 | semver "^5.1.0" 2238 | 2239 | resolve-from@^2.0.0: 2240 | version "2.0.0" 2241 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" 2242 | integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= 2243 | 2244 | resolve-url@^0.2.1: 2245 | version "0.2.1" 2246 | resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" 2247 | integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= 2248 | 2249 | resolve@^1.10.0: 2250 | version "1.17.0" 2251 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" 2252 | integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== 2253 | dependencies: 2254 | path-parse "^1.0.6" 2255 | 2256 | ret@~0.1.10: 2257 | version "0.1.15" 2258 | resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" 2259 | integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== 2260 | 2261 | rimraf@^2.6.1, rimraf@^2.6.2: 2262 | version "2.7.1" 2263 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" 2264 | integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 2265 | dependencies: 2266 | glob "^7.1.3" 2267 | 2268 | safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 2269 | version "5.1.2" 2270 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 2271 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 2272 | 2273 | safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2: 2274 | version "5.2.1" 2275 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 2276 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 2277 | 2278 | safe-regex@^1.1.0: 2279 | version "1.1.0" 2280 | resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" 2281 | integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= 2282 | dependencies: 2283 | ret "~0.1.10" 2284 | 2285 | safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 2286 | version "2.1.2" 2287 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 2288 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 2289 | 2290 | saslprep@^1.0.0: 2291 | version "1.0.3" 2292 | resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" 2293 | integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== 2294 | dependencies: 2295 | sparse-bitfield "^3.0.3" 2296 | 2297 | "semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0: 2298 | version "5.7.2" 2299 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" 2300 | integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== 2301 | 2302 | set-blocking@^2.0.0: 2303 | version "2.0.0" 2304 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 2305 | integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= 2306 | 2307 | set-value@^2.0.0, set-value@^2.0.1: 2308 | version "2.0.1" 2309 | resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" 2310 | integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== 2311 | dependencies: 2312 | extend-shallow "^2.0.1" 2313 | is-extendable "^0.1.1" 2314 | is-plain-object "^2.0.3" 2315 | split-string "^3.0.1" 2316 | 2317 | shebang-command@^1.2.0: 2318 | version "1.2.0" 2319 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 2320 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 2321 | dependencies: 2322 | shebang-regex "^1.0.0" 2323 | 2324 | shebang-regex@^1.0.0: 2325 | version "1.0.0" 2326 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 2327 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 2328 | 2329 | shelljs@0.3.x: 2330 | version "0.3.0" 2331 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" 2332 | integrity sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E= 2333 | 2334 | sift@7.0.1: 2335 | version "7.0.1" 2336 | resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08" 2337 | integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g== 2338 | 2339 | signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: 2340 | version "3.0.3" 2341 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 2342 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 2343 | 2344 | sliced@1.0.1: 2345 | version "1.0.1" 2346 | resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" 2347 | integrity sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E= 2348 | 2349 | slide@^1.1.5: 2350 | version "1.1.6" 2351 | resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" 2352 | integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= 2353 | 2354 | snapdragon-node@^2.0.1: 2355 | version "2.1.1" 2356 | resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" 2357 | integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== 2358 | dependencies: 2359 | define-property "^1.0.0" 2360 | isobject "^3.0.0" 2361 | snapdragon-util "^3.0.1" 2362 | 2363 | snapdragon-util@^3.0.1: 2364 | version "3.0.1" 2365 | resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" 2366 | integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== 2367 | dependencies: 2368 | kind-of "^3.2.0" 2369 | 2370 | snapdragon@^0.8.1: 2371 | version "0.8.2" 2372 | resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" 2373 | integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== 2374 | dependencies: 2375 | base "^0.11.1" 2376 | debug "^2.2.0" 2377 | define-property "^0.2.5" 2378 | extend-shallow "^2.0.1" 2379 | map-cache "^0.2.2" 2380 | source-map "^0.5.6" 2381 | source-map-resolve "^0.5.0" 2382 | use "^3.1.0" 2383 | 2384 | source-map-resolve@^0.5.0: 2385 | version "0.5.3" 2386 | resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" 2387 | integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== 2388 | dependencies: 2389 | atob "^2.1.2" 2390 | decode-uri-component "^0.2.0" 2391 | resolve-url "^0.2.1" 2392 | source-map-url "^0.4.0" 2393 | urix "^0.1.0" 2394 | 2395 | source-map-url@^0.4.0: 2396 | version "0.4.0" 2397 | resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" 2398 | integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= 2399 | 2400 | source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: 2401 | version "0.5.7" 2402 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 2403 | integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= 2404 | 2405 | source-map@^0.6.1: 2406 | version "0.6.1" 2407 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 2408 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 2409 | 2410 | sparse-bitfield@^3.0.3: 2411 | version "3.0.3" 2412 | resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" 2413 | integrity sha1-/0rm5oZWBWuks+eSqzM004JzyhE= 2414 | dependencies: 2415 | memory-pager "^1.0.2" 2416 | 2417 | spawn-wrap@^1.4.2: 2418 | version "1.4.3" 2419 | resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.3.tgz#81b7670e170cca247d80bf5faf0cfb713bdcf848" 2420 | integrity sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw== 2421 | dependencies: 2422 | foreground-child "^1.5.6" 2423 | mkdirp "^0.5.0" 2424 | os-homedir "^1.0.1" 2425 | rimraf "^2.6.2" 2426 | signal-exit "^3.0.2" 2427 | which "^1.3.0" 2428 | 2429 | spdx-correct@^3.0.0: 2430 | version "3.1.1" 2431 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" 2432 | integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== 2433 | dependencies: 2434 | spdx-expression-parse "^3.0.0" 2435 | spdx-license-ids "^3.0.0" 2436 | 2437 | spdx-exceptions@^2.1.0: 2438 | version "2.3.0" 2439 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" 2440 | integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== 2441 | 2442 | spdx-expression-parse@^3.0.0: 2443 | version "3.0.1" 2444 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" 2445 | integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== 2446 | dependencies: 2447 | spdx-exceptions "^2.1.0" 2448 | spdx-license-ids "^3.0.0" 2449 | 2450 | spdx-license-ids@^3.0.0: 2451 | version "3.0.5" 2452 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" 2453 | integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== 2454 | 2455 | split-string@^3.0.1, split-string@^3.0.2: 2456 | version "3.1.0" 2457 | resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" 2458 | integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== 2459 | dependencies: 2460 | extend-shallow "^3.0.0" 2461 | 2462 | sprintf-js@~1.0.2: 2463 | version "1.0.3" 2464 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 2465 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 2466 | 2467 | sshpk@^1.7.0: 2468 | version "1.16.1" 2469 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" 2470 | integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== 2471 | dependencies: 2472 | asn1 "~0.2.3" 2473 | assert-plus "^1.0.0" 2474 | bcrypt-pbkdf "^1.0.0" 2475 | dashdash "^1.12.0" 2476 | ecc-jsbn "~0.1.1" 2477 | getpass "^0.1.1" 2478 | jsbn "~0.1.0" 2479 | safer-buffer "^2.0.2" 2480 | tweetnacl "~0.14.0" 2481 | 2482 | static-extend@^0.1.1: 2483 | version "0.1.2" 2484 | resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" 2485 | integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= 2486 | dependencies: 2487 | define-property "^0.2.5" 2488 | object-copy "^0.1.0" 2489 | 2490 | string-width@^1.0.1: 2491 | version "1.0.2" 2492 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 2493 | integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 2494 | dependencies: 2495 | code-point-at "^1.0.0" 2496 | is-fullwidth-code-point "^1.0.0" 2497 | strip-ansi "^3.0.0" 2498 | 2499 | string-width@^2.0.0, string-width@^2.1.1: 2500 | version "2.1.1" 2501 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 2502 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 2503 | dependencies: 2504 | is-fullwidth-code-point "^2.0.0" 2505 | strip-ansi "^4.0.0" 2506 | 2507 | string_decoder@~0.10.x: 2508 | version "0.10.31" 2509 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 2510 | integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= 2511 | 2512 | string_decoder@~1.0.0: 2513 | version "1.0.3" 2514 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 2515 | integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== 2516 | dependencies: 2517 | safe-buffer "~5.1.0" 2518 | 2519 | string_decoder@~1.1.1: 2520 | version "1.1.1" 2521 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 2522 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 2523 | dependencies: 2524 | safe-buffer "~5.1.0" 2525 | 2526 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 2527 | version "3.0.1" 2528 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 2529 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 2530 | dependencies: 2531 | ansi-regex "^2.0.0" 2532 | 2533 | strip-ansi@^4.0.0: 2534 | version "4.0.0" 2535 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 2536 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 2537 | dependencies: 2538 | ansi-regex "^3.0.0" 2539 | 2540 | strip-bom@^2.0.0: 2541 | version "2.0.0" 2542 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 2543 | integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= 2544 | dependencies: 2545 | is-utf8 "^0.2.0" 2546 | 2547 | strip-eof@^1.0.0: 2548 | version "1.0.0" 2549 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 2550 | integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= 2551 | 2552 | strip-json-comments@1.0.x: 2553 | version "1.0.4" 2554 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" 2555 | integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= 2556 | 2557 | supports-color@5.4.0: 2558 | version "5.4.0" 2559 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" 2560 | integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== 2561 | dependencies: 2562 | has-flag "^3.0.0" 2563 | 2564 | supports-color@^2.0.0: 2565 | version "2.0.0" 2566 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 2567 | integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= 2568 | 2569 | supports-color@^3.1.2: 2570 | version "3.2.3" 2571 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" 2572 | integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= 2573 | dependencies: 2574 | has-flag "^1.0.0" 2575 | 2576 | test-exclude@^4.2.0: 2577 | version "4.2.3" 2578 | resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20" 2579 | integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA== 2580 | dependencies: 2581 | arrify "^1.0.1" 2582 | micromatch "^2.3.11" 2583 | object-assign "^4.1.0" 2584 | read-pkg-up "^1.0.1" 2585 | require-main-filename "^1.0.1" 2586 | 2587 | to-fast-properties@^1.0.3: 2588 | version "1.0.3" 2589 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" 2590 | integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= 2591 | 2592 | to-object-path@^0.3.0: 2593 | version "0.3.0" 2594 | resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" 2595 | integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= 2596 | dependencies: 2597 | kind-of "^3.0.2" 2598 | 2599 | to-regex-range@^2.1.0: 2600 | version "2.1.1" 2601 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" 2602 | integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= 2603 | dependencies: 2604 | is-number "^3.0.0" 2605 | repeat-string "^1.6.1" 2606 | 2607 | to-regex@^3.0.1, to-regex@^3.0.2: 2608 | version "3.0.2" 2609 | resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" 2610 | integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== 2611 | dependencies: 2612 | define-property "^2.0.2" 2613 | extend-shallow "^3.0.2" 2614 | regex-not "^1.0.2" 2615 | safe-regex "^1.1.0" 2616 | 2617 | tough-cookie@~2.5.0: 2618 | version "2.5.0" 2619 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" 2620 | integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== 2621 | dependencies: 2622 | psl "^1.1.28" 2623 | punycode "^2.1.1" 2624 | 2625 | trim-right@^1.0.1: 2626 | version "1.0.1" 2627 | resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" 2628 | integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= 2629 | 2630 | tunnel-agent@^0.6.0: 2631 | version "0.6.0" 2632 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 2633 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 2634 | dependencies: 2635 | safe-buffer "^5.0.1" 2636 | 2637 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 2638 | version "0.14.5" 2639 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 2640 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= 2641 | 2642 | type-detect@^4.0.0, type-detect@^4.0.5: 2643 | version "4.0.8" 2644 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" 2645 | integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== 2646 | 2647 | uglify-js@^3.1.4: 2648 | version "3.13.5" 2649 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.5.tgz#5d71d6dbba64cf441f32929b1efce7365bb4f113" 2650 | integrity sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw== 2651 | 2652 | union-value@^1.0.0: 2653 | version "1.0.1" 2654 | resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" 2655 | integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== 2656 | dependencies: 2657 | arr-union "^3.1.0" 2658 | get-value "^2.0.6" 2659 | is-extendable "^0.1.1" 2660 | set-value "^2.0.1" 2661 | 2662 | unset-value@^1.0.0: 2663 | version "1.0.0" 2664 | resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" 2665 | integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= 2666 | dependencies: 2667 | has-value "^0.3.1" 2668 | isobject "^3.0.0" 2669 | 2670 | uri-js@^4.2.2: 2671 | version "4.2.2" 2672 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 2673 | integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== 2674 | dependencies: 2675 | punycode "^2.1.0" 2676 | 2677 | urix@^0.1.0: 2678 | version "0.1.0" 2679 | resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" 2680 | integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= 2681 | 2682 | use@^3.1.0: 2683 | version "3.1.1" 2684 | resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" 2685 | integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== 2686 | 2687 | util-deprecate@~1.0.1: 2688 | version "1.0.2" 2689 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 2690 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 2691 | 2692 | uuid@^3.3.2: 2693 | version "3.4.0" 2694 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 2695 | integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== 2696 | 2697 | validate-npm-package-license@^3.0.1: 2698 | version "3.0.4" 2699 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 2700 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 2701 | dependencies: 2702 | spdx-correct "^3.0.0" 2703 | spdx-expression-parse "^3.0.0" 2704 | 2705 | verror@1.10.0: 2706 | version "1.10.0" 2707 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 2708 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= 2709 | dependencies: 2710 | assert-plus "^1.0.0" 2711 | core-util-is "1.0.2" 2712 | extsprintf "^1.2.0" 2713 | 2714 | which-module@^2.0.0: 2715 | version "2.0.0" 2716 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 2717 | integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= 2718 | 2719 | which@^1.2.9, which@^1.3.0: 2720 | version "1.3.1" 2721 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 2722 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 2723 | dependencies: 2724 | isexe "^2.0.0" 2725 | 2726 | wordwrap@^1.0.0: 2727 | version "1.0.0" 2728 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 2729 | integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= 2730 | 2731 | wrap-ansi@^2.0.0: 2732 | version "2.1.0" 2733 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" 2734 | integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= 2735 | dependencies: 2736 | string-width "^1.0.1" 2737 | strip-ansi "^3.0.1" 2738 | 2739 | wrappy@1: 2740 | version "1.0.2" 2741 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 2742 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 2743 | 2744 | write-file-atomic@^1.1.4: 2745 | version "1.3.4" 2746 | resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" 2747 | integrity sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8= 2748 | dependencies: 2749 | graceful-fs "^4.1.11" 2750 | imurmurhash "^0.1.4" 2751 | slide "^1.1.5" 2752 | 2753 | y18n@^3.2.1: 2754 | version "3.2.2" 2755 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" 2756 | integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== 2757 | 2758 | yallist@^2.1.2: 2759 | version "2.1.2" 2760 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 2761 | integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= 2762 | 2763 | yargs-parser@^8.0.0, yargs-parser@^8.1.0: 2764 | version "8.1.0" 2765 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" 2766 | integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== 2767 | dependencies: 2768 | camelcase "^4.1.0" 2769 | 2770 | yargs-parser@^9.0.2: 2771 | version "9.0.2" 2772 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" 2773 | integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= 2774 | dependencies: 2775 | camelcase "^4.1.0" 2776 | 2777 | yargs@11.1.0: 2778 | version "11.1.0" 2779 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" 2780 | integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== 2781 | dependencies: 2782 | cliui "^4.0.0" 2783 | decamelize "^1.1.1" 2784 | find-up "^2.1.0" 2785 | get-caller-file "^1.0.1" 2786 | os-locale "^2.0.0" 2787 | require-directory "^2.1.1" 2788 | require-main-filename "^1.0.1" 2789 | set-blocking "^2.0.0" 2790 | string-width "^2.0.0" 2791 | which-module "^2.0.0" 2792 | y18n "^3.2.1" 2793 | yargs-parser "^9.0.2" 2794 | 2795 | yargs@^10.0.3: 2796 | version "10.1.2" 2797 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" 2798 | integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== 2799 | dependencies: 2800 | cliui "^4.0.0" 2801 | decamelize "^1.1.1" 2802 | find-up "^2.1.0" 2803 | get-caller-file "^1.0.1" 2804 | os-locale "^2.0.0" 2805 | require-directory "^2.1.1" 2806 | require-main-filename "^1.0.1" 2807 | set-blocking "^2.0.0" 2808 | string-width "^2.0.0" 2809 | which-module "^2.0.0" 2810 | y18n "^3.2.1" 2811 | yargs-parser "^8.1.0" 2812 | --------------------------------------------------------------------------------