├── examples └── wikipedia-list-links │ ├── .gitignore │ ├── package.json │ ├── tsconfig.json │ ├── src │ └── index.ts │ ├── yarn.lock │ └── package-lock.json ├── .travis.yml ├── .gitignore ├── src ├── .eslintrc ├── index.ts ├── fix.ts └── ChainedPromise.ts ├── tsconfig.json ├── package.json ├── CONTRIBUTING ├── README.md ├── test ├── fix.spec.ts └── ChainedPromise.spec.ts └── LICENSE /examples/wikipedia-list-links/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | script: yarn travis 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/* 2 | .idea/ 3 | **/*.iml 4 | node_modules/ 5 | coverage/ 6 | docs/ 7 | yarn.lock 8 | -------------------------------------------------------------------------------- /src/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | // disallow use of undeclared variables unless mentioned in a /*global */ block 4 | "no-undef": 2 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/wikipedia-list-links/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wikipedia-list-links", 3 | "version": "0.0.1", 4 | "description": "ChainedPromise example to list links from wikipedia page", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "start": "tsc && node dist/index.js" 8 | }, 9 | "dependencies": { 10 | "chained-promise": "../../.", 11 | "node-fetch": "^1.7.3" 12 | }, 13 | "devDependencies": { 14 | "@types/node-fetch": "^1.6.7", 15 | "typescript": "^2.5.3" 16 | }, 17 | "license": "Apache-2.0" 18 | } 19 | -------------------------------------------------------------------------------- /examples/wikipedia-list-links/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "outDir": "./dist", 7 | "moduleResolution": "node", 8 | "rootDirs": [ 9 | "./src" 10 | ], 11 | "baseUrl": "./", 12 | "paths": { 13 | "src": [ 14 | "src/" 15 | ] 16 | }, 17 | /* Strict Type-Checking Options */ 18 | "strictNullChecks": true, 19 | "noImplicitThis": true, 20 | /* Additional Checks */ 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "noImplicitReturns": true, 24 | "noFallthroughCasesInSwitch": true 25 | }, 26 | "exclude": [ 27 | "node_modules", 28 | "dist" 29 | ] 30 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "outDir": "./dist", 8 | "rootDirs": [ 9 | "./src", 10 | "./test" 11 | ], 12 | "baseUrl": "./", 13 | "paths": { 14 | "src": [ 15 | "src/" 16 | ], 17 | "test": [ 18 | "test/" 19 | ] 20 | }, 21 | /* Strict Type-Checking Options */ 22 | "strictNullChecks": true, 23 | "noImplicitThis": true, 24 | /* Additional Checks */ 25 | "noUnusedLocals": true, 26 | "noUnusedParameters": true, 27 | "noImplicitReturns": true, 28 | "noFallthroughCasesInSwitch": true 29 | }, 30 | "exclude": [ 31 | "node_modules", 32 | "examples", 33 | "dist" 34 | ] 35 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2017 Google Inc. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import fix from "./fix"; 17 | import ChainedPromise from "./ChainedPromise"; 18 | 19 | export {fix, ChainedPromise}; 20 | export default ChainedPromise; 21 | -------------------------------------------------------------------------------- /examples/wikipedia-list-links/src/index.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | import ChainedPromise from 'chained-promise'; 3 | const apiPoint = 'https://en.wikipedia.org/w/api.php?' + 4 | 'action=query&prop=links&format=json&plnamespace=0&titles=Plato&pllimit=100'; 5 | 6 | ChainedPromise.from(fetch(apiPoint)) 7 | .flatMap((res) => res.json()) 8 | .map((v) => { 9 | return { 10 | data: v.query.pages, 11 | next: v.continue ? 12 | fetch(apiPoint + '&plcontinue=' + encodeURIComponent(v.continue.plcontinue)) : 13 | {[ChainedPromise.DONE]: 'done fetching links from Plato page'} 14 | }; 15 | }) 16 | .forEach((v) => { 17 | Object.keys(v.data).forEach((pageId) => { 18 | v.data[pageId].links.forEach((link) => { 19 | console.log(link.title); 20 | }); 21 | }); 22 | }) 23 | .then((v) => { 24 | console.log(v); 25 | }) 26 | .catch((err) => console.error(err.stack, err)); 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chained-promise", 3 | "version": "0.2.5", 4 | "description": "Functional programming tools for recurring promises", 5 | "main": "dist/src/index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/google/chained-promise.git" 9 | }, 10 | "files": [ 11 | "dist/src/*", 12 | "src/*", 13 | "README.md", 14 | "LICENSE" 15 | ], 16 | "scripts": { 17 | "build": "tsc", 18 | "test": "jest", 19 | "coveralls": "jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js", 20 | "travis": "jest", 21 | "posttravis": "yarn coveralls", 22 | "doc": "typedoc --out docs/ src/" 23 | }, 24 | "authors": [ 25 | "In-Ho Yi " 26 | ], 27 | "license": "Apache-2.0", 28 | "devDependencies": { 29 | "@types/jest": "^22.1.2", 30 | "coveralls": "^3.0.0", 31 | "jest": "^22.3.0", 32 | "ts-jest": "^22.0.4", 33 | "typedoc": "^0.10.0", 34 | "typescript": "^2.7.1" 35 | }, 36 | "jest": { 37 | "moduleFileExtensions": [ 38 | "ts", 39 | "tsx", 40 | "js" 41 | ], 42 | "transform": { 43 | "\\.(ts|tsx)$": "/node_modules/ts-jest/preprocessor.js" 44 | }, 45 | "roots": [ 46 | "src", 47 | "test" 48 | ], 49 | "testRegex": "test/.*\\.ts", 50 | "moduleDirectories": [ 51 | "node_modules", 52 | "." 53 | ], 54 | "mapCoverage": true, 55 | "collectCoverage": true 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | Want to contribute? Great! First, read this page (including the small print at the end). 2 | 3 | ### Before you contribute 4 | Before we can use your code, you must sign the 5 | [Google Individual Contributor License Agreement] 6 | (https://cla.developers.google.com/about/google-individual) 7 | (CLA), which you can do online. The CLA is necessary mainly because you own the 8 | copyright to your changes, even after your contribution becomes part of our 9 | codebase, so we need your permission to use and distribute your code. We also 10 | need to be sure of various other things—for instance that you'll tell us if you 11 | know that your code infringes on other people's patents. You don't have to sign 12 | the CLA until after you've submitted your code for review and a member has 13 | approved it, but you must do it before we can put your code into our codebase. 14 | Before you start working on a larger contribution, you should get in touch with 15 | us first through the issue tracker with your idea so that we can help out and 16 | possibly guide you. Coordinating up front makes it much easier to avoid 17 | frustration later on. 18 | 19 | ### Code reviews 20 | All submissions, including submissions by project members, require review. We 21 | use Github pull requests for this purpose. 22 | 23 | ### The small print 24 | Contributions made by corporations are covered by a different agreement than 25 | the one above, the 26 | [Software Grant and Corporate Contributor License Agreement] 27 | (https://cla.developers.google.com/about/google-corporate). -------------------------------------------------------------------------------- /examples/wikipedia-list-links/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/node-fetch@^1.6.7": 6 | version "1.6.7" 7 | resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-1.6.7.tgz#521078e8f0c69a158e5022005aca92d2620f6d57" 8 | dependencies: 9 | "@types/node" "*" 10 | 11 | "@types/node@*": 12 | version "8.0.46" 13 | resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.46.tgz#6e1766b2d0ed06631d5b5f87bb8e72c8dbb6888e" 14 | 15 | chained-promise@../../.: 16 | version "0.2.0" 17 | 18 | encoding@^0.1.11: 19 | version "0.1.12" 20 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 21 | dependencies: 22 | iconv-lite "~0.4.13" 23 | 24 | iconv-lite@~0.4.13: 25 | version "0.4.19" 26 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" 27 | 28 | is-stream@^1.0.1: 29 | version "1.1.0" 30 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 31 | 32 | node-fetch@^1.7.3: 33 | version "1.7.3" 34 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" 35 | dependencies: 36 | encoding "^0.1.11" 37 | is-stream "^1.0.1" 38 | 39 | typescript@^2.5.3: 40 | version "2.5.3" 41 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d" 42 | -------------------------------------------------------------------------------- /src/fix.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2017 Google Inc. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /** 17 | * Fix operator that continuously resolves next promise returned from the 18 | * function that consumes previously resolved value. 19 | * 20 | * ```javascript 21 | * fix(fn)(promise).catch(errorHandler); 22 | * ``` 23 | * 24 | * is equivalent to: 25 | * 26 | * ```javascript 27 | * promise.then(fn).then(fn).then(fn) ... 28 | * .catch(errorHandler); 29 | * ``` 30 | * 31 | * In addition, the function can complete the chain by calling the complete 32 | * callback function supplied as the second argument. 33 | * 34 | * For example, the following code fragment calculates 5! 35 | * 36 | * ```javascript 37 | * var promiseFactorial = (v, complete) => { 38 | * if (v.i==5) { 39 | * complete(v.f); 40 | * } else { 41 | * return Promise.resolve({i: v.i+1, f: v.f * (v.i + 1)}); 42 | * } 43 | * }; 44 | * 45 | * fix(promiseFactorial)(Promise.resolve({i:1, f:1})).then(console.log); 46 | * ``` 47 | * 48 | * @param {function(T, function(U)) : Promise} fn 49 | * @returns {function(Promise.) : Promise.} 50 | * @template T 51 | * @template U 52 | */ 53 | const fix = ( 54 | fn: (current: T, next: (completed: U) => void) => Promise| void) => 55 | (promise) => { 56 | /** 57 | * Resolve handler to resolve the resulting promise and end the chain. 58 | */ 59 | let finalResolver; 60 | let rejecter; 61 | let resolver: ((c: T) => void)|null = (v) => { 62 | try { 63 | let completeCalled = false; 64 | let completeValue; 65 | let complete: ((vComplete: U) => void)|null = (vComplete: U) => { 66 | completeCalled = true; 67 | completeValue = vComplete; 68 | }; 69 | const nextPromise = fn(v, complete); 70 | if (completeCalled) { 71 | finalResolver(completeValue); 72 | resolver = null; 73 | } else { 74 | nextPromise!.then(resolver as any, rejecter as any); 75 | } 76 | complete = null; 77 | } catch (err) { 78 | rejecter(err); 79 | } 80 | }; 81 | return new Promise((resolve, reject) => { 82 | finalResolver = resolve; 83 | rejecter = reject; 84 | promise.then(resolver, reject); 85 | }); 86 | }; 87 | 88 | export default fix; 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chained Promise: functional programming tools for recurring promises 2 | 3 | [![Build Status](https://travis-ci.org/google/chained-promise.svg?branch=travis-ci)](https://travis-ci.org/google/chained-promise) [![Coverage Status](https://coveralls.io/repos/google/chained-promise/badge.svg?branch=master&service=github)](https://coveralls.io/github/google/chained-promise?branch=master) [![Join the chat at https://gitter.im/google/chained-promise](https://badges.gitter.im/google/chained-promise.svg)](https://gitter.im/google/chained-promise?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | We often find recurring patterns when handling asynchronous logic with promises, such as an HTTP endpoint that paginates and gives you a URL pointer to the next available dataset. 6 | 7 | `Chained Promise` provides an extended Promise class that you can use to easily abstract out recurring patterns. See jsdocs for more detailed explanations. 8 | 9 | ## Example 10 | 11 | Suppose we are querying Wikipedia API to get the list of all linked pages from "Plato" page: 12 | 13 | ```javascript 14 | const apiPoint = "https://en.wikipedia.org/w/api.php?" + 15 | "action=query&prop=links&format=json&plnamespace=0&titles=Plato&pllimit=500"; 16 | ``` 17 | 18 | With `fetch` we can turn the end point into a promise. Then we can use `ChainedPromise` to extend the promise: 19 | 20 | ```javascript 21 | import ChainedPromise from "chained-promise"; 22 | 23 | ChainedPromise.from(fetch(apiPoint)) 24 | ``` 25 | 26 | First thing we want to do is to parse the resulting JSON: 27 | 28 | ```javascript 29 | .flatMap((res) => res.json()) 30 | ``` 31 | 32 | Now we have a promise that resolves into a JS object. Next we need to map the result into the format that `ChainedPromise` is expecting. 33 | 34 | ```javascript 35 | .map((v) => { 36 | return { 37 | data: v.query.pages, 38 | next: v.continue ? 39 | fetch(apiPoint + '&plcontinue=' + encodeURIComponent(v.continue.plcontinue)) : 40 | {[ChainedPromise.DONE]: 'done fetching links from Plato page'} 41 | }; 42 | }) 43 | ``` 44 | 45 | The `data` field contains the material content of the value, while the `next` field contains either the promise to the next batch of data, or `{[ChainedPromise.DONE]: lastNode}` which `ChainedPromise` recognizes to be the terminal node. 46 | 47 | Now that the chaining of the value has been configured, we can work on the series of data. 48 | 49 | ```javascript 50 | .forEach((v) => { 51 | Object.keys(v.data).forEach((pageId) => { 52 | v.data[pageId].links.forEach((link) => { 53 | console.log(link.title); 54 | }); 55 | }); 56 | }) 57 | ``` 58 | 59 | This executes the given callback function, and the result itself is a promise that resolves into the value of the terminal node when it reaches the end. 60 | 61 | See [the example project](examples/wikipedia-list-links) for the full example code. Also see jsdoc to [ChainedPromise.ts](src/ChainedPromise.ts) for more explanation of other functions such as `flatMap`. 62 | 63 | Disclaimer: This is not an official Google product. 64 | -------------------------------------------------------------------------------- /test/fix.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2017 Google Inc. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import {fix} from '../src/index'; 17 | 18 | const nullPromise = new Promise(() => undefined); 19 | 20 | describe('fix', function() { 21 | it('resolves to next promise', function(done) { 22 | const valueResolved : Array = []; 23 | const testPromises = { 24 | 1: Promise.resolve(1), 25 | 2: Promise.resolve(2), 26 | 3: Promise.resolve(3) 27 | }; 28 | const testFn = (v) => { 29 | valueResolved.push(v); 30 | if (v < 3) { 31 | return testPromises[v + 1]; 32 | } else { 33 | expect(valueResolved).toEqual([1, 2, 3]); 34 | done(); 35 | return nullPromise; 36 | } 37 | }; 38 | fix(testFn)(testPromises[1]).catch((err) => console.error(err.stack, err)); 39 | }); 40 | it('rejects with error from promise in chain', function(done) { 41 | const valueResolved : Array = []; 42 | const testPromises = { 43 | 1: Promise.resolve(1), 44 | 2: Promise.resolve(2), 45 | 3: Promise.reject(3) 46 | }; 47 | const testFn = (v) => { 48 | valueResolved.push(v); 49 | expect(v < 3).toBeTruthy; 50 | return testPromises[v + 1]; 51 | }; 52 | fix(testFn)(testPromises[1]).catch((err) => { 53 | expect(valueResolved).toEqual([1, 2]); 54 | expect(err).toEqual(3); 55 | done(); 56 | }); 57 | }); 58 | it('rejects with error when function throws', function(done) { 59 | const valueResolved : Array = []; 60 | const testPromises = { 61 | 1: Promise.resolve(1), 62 | 2: Promise.resolve(2), 63 | 3: Promise.resolve(3) 64 | }; 65 | const testFn = (v) => { 66 | valueResolved.push(v); 67 | if (v < 3) { 68 | return testPromises[v + 1]; 69 | } else { 70 | throw 'testError'; 71 | } 72 | }; 73 | fix(testFn)(testPromises[1]).catch((err) => { 74 | expect(valueResolved).toEqual([1, 2, 3]); 75 | expect(err).toEqual('testError'); 76 | done(); 77 | }); 78 | }); 79 | it('stops the chain when complete call is made', function(done) { 80 | const factorialFiveFn = (v, complete) => { 81 | if (v.i === 5) { 82 | // If this it fifth iteration, complete the chain with the given 83 | // factorial value. 84 | return complete(v.f); 85 | } else { 86 | // Otherwise return a promise that resolves into the next iteration. 87 | return Promise.resolve({i: v.i + 1, f: v.f * (v.i + 1)}); 88 | } 89 | }; 90 | const initialPromise = Promise.resolve({i: 1, f: 1}); 91 | fix(factorialFiveFn)(initialPromise) 92 | .then((v) => { 93 | expect(v).toEqual(120); // 5! 94 | done(); 95 | }) 96 | .catch((err) => console.error(err.stack, err)); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /src/ChainedPromise.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2017 Google Inc. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import fix from './fix'; 17 | 18 | type SkipToken = { 19 | data: symbol, 20 | next: ChainedPromise 21 | }; 22 | 23 | /** 24 | * An extended promise for recurring promises with multiple compositions. 25 | * 26 | * ```javascript 27 | * var chained = ChainedPromise.from(promise); 28 | * chained.flatMap(a).flatMap(b).flatMap(c).forEach(fn).catch(onRejected); 29 | * ``` 30 | * 31 | * is equivalent to: 32 | * 33 | * ```javascript 34 | * promise.then(a).then(b).then(c).then(fn).then((v) => v.next) 35 | * .then(a).then(b).then(c).then(fn).then((v) => v.next) 36 | * .then(a).then(b).then(c).then(fn).then((v) => v.next) 37 | * ... 38 | * .catch(onRejected); 39 | * ``` 40 | * 41 | * `(v) => v.next` function is the default {@link ChainedPromise#next} value 42 | * picker. We can supply custom value picker to the {@link 43 | * ChainedPromise#constructor} and {@link ChainedPromise#from}. 44 | */ 45 | class ChainedPromise extends Promise { 46 | private flatMapChain: Array<(v: any) => Promise>; 47 | 48 | /** 49 | * Function to construct promise to next item in chain. 50 | */ 51 | public next: (t: T) => Promise; 52 | 53 | /** 54 | * Initializes fields common to both {@link ChainedPromise#constructor} 55 | * and {@link ChainedPromise#from} code path. 56 | */ 57 | private initialize() { 58 | this.flatMapChain = []; 59 | } 60 | 61 | /** 62 | * Constructs next {@link ChainedPromise} that carries over settings and 63 | * composition properties of the current one. 64 | */ 65 | private nextPromise(v: T|SkipToken): ChainedPromise { 66 | let nextPromise; 67 | if ((v as SkipToken).data && 68 | (v as SkipToken).data === ChainedPromise.SKIP) { 69 | nextPromise = ChainedPromise.from((v as SkipToken).next, this.next); 70 | } else { 71 | nextPromise = ChainedPromise.from(this.next(v as T), this.next); 72 | } 73 | nextPromise.flatMapChain = this.flatMapChain; 74 | return ((nextPromise as any) as ChainedPromise); 75 | } 76 | 77 | /** 78 | * @param executor Promise executor 79 | * @param next 80 | */ 81 | constructor(executor, next = ChainedPromise.nextFieldPicker('next')) { 82 | super(executor); 83 | this.next = next; 84 | this.initialize(); 85 | } 86 | 87 | /** 88 | * Creates a ChainedPromise that extends given Promise. 89 | */ 90 | static from( 91 | innerPromise: Promise, 92 | next = ChainedPromise.nextFieldPicker('next')): ChainedPromise { 93 | return new ChainedPromise((res, rej) => innerPromise.then(res, rej), next); 94 | } 95 | 96 | /** 97 | * Returns a function to pick the given attribute. 98 | * @param {string} attr Name of the attribute (that will contain the next promise). 99 | * @returns {function(T) : Promise.} 100 | * @template T 101 | */ 102 | static nextFieldPicker(attr: string): (v: T) => Promise { 103 | return (x) => x[attr]; 104 | } 105 | 106 | /** 107 | * Creates `[ChainedPromise, callback, error]` array. 108 | * 109 | * Calling callback with a value `v` will cause the promise to be resolved 110 | * into 111 | * `{data: v, next: nextPromise}`, `nextPromise` being another {@link 112 | * ChainedPromise} who gets resolved next time `callback` is called. 113 | * 114 | * Calling `error` function will cause the promise to be rejected. 115 | * @returns {Array} 116 | * @template T 117 | */ 118 | static createPromiseCallbackPair}>(): 119 | [ChainedPromise, (v: U) => void, (error: any) => void] { 120 | let resolver; 121 | let rejecter; 122 | const callback = (v) => { 123 | const oldResolver = resolver; 124 | const nextPromise = new ChainedPromise((resolve, reject) => { 125 | resolver = resolve; 126 | rejecter = reject; 127 | }); 128 | oldResolver({data: v, next: nextPromise}); 129 | }; 130 | const error = (err) => { 131 | rejecter(err); 132 | }; 133 | const promise = new ChainedPromise((resolve, reject) => { 134 | resolver = resolve; 135 | rejecter = reject; 136 | }); 137 | return [promise, callback, error]; 138 | } 139 | 140 | /** 141 | * Applies the given function on all values in the chain, until the {@link 142 | * ChainedPromise#next} value returns an object with {@link 143 | * ChainedPromise.DONE} symbol. 144 | */ 145 | forEach(fn: (v: T) => void): Promise { 146 | return fix((v: T|SkipToken, complete) => { 147 | let nextPromise; 148 | if ((v as SkipToken).data && 149 | (v as SkipToken).data === ChainedPromise.SKIP) { 150 | nextPromise = (v as SkipToken).next; 151 | } else { 152 | fn(v as T); 153 | nextPromise = this.next(v as T); 154 | } 155 | if (nextPromise[ChainedPromise.DONE] !== undefined) { 156 | return complete(nextPromise[ChainedPromise.DONE]); 157 | } else { 158 | return this.nextPromise(v as T); 159 | } 160 | })(this); 161 | } 162 | 163 | /** 164 | * Stacks up flat map operation to be performed in this promise. See {@link 165 | * ChainedPromise} for examples. 166 | */ 167 | flatMap(fn: (v: T) => Promise): ChainedPromise { 168 | this.flatMapChain.push(fn); 169 | return ((this as any) as ChainedPromise); 170 | } 171 | 172 | /** 173 | * Non-async equivalent of {@link ChainedPromise#flatMap}. 174 | */ 175 | map(fn: (T) => U): ChainedPromise { 176 | this.flatMap((v) => new ChainedPromise((res) => res(fn(v)))); 177 | return ((this as any) as ChainedPromise); 178 | } 179 | 180 | /** 181 | * Overrides Promise.then to compose with extra functions. See {@link 182 | * ChainedPromise} for the specifics of available compositions. 183 | */ 184 | then, TResult2 = never>( 185 | onFulfilled?: ((value: T) => TResult1 | PromiseLike)|null| 186 | undefined, 187 | onRejected?: (result: any) => TResult2 | 188 | PromiseLike): Promise { 189 | if (!onFulfilled) { 190 | // Skip processing in case of Promise.catch call. 191 | // TODO: fix type. 192 | return super.then(onFulfilled as any, onRejected as any) as any; 193 | } 194 | // Branch out no-op special case, since "super" in ES6 is not a first-class 195 | // citizen. 196 | if (this.flatMapChain.length === 0) { 197 | // TODO: fix type. 198 | return super.then(onFulfilled as any, onRejected as any) as any; 199 | } else { 200 | const firstFlatMapped = super.then(this.flatMapChain[0]); 201 | let flatMapped = this.flatMapChain.slice(1).reduce((x, y) => { 202 | return x.then((res) => { 203 | if (res.data && res.data === ChainedPromise.SKIP) { 204 | return res; 205 | } 206 | return y(res); 207 | }); 208 | }, firstFlatMapped); 209 | return flatMapped.then(onFulfilled, onRejected); 210 | } 211 | } 212 | 213 | /** 214 | * Flat-maps current promise chain to resolve into successive accumulation of 215 | * values, from given accumulator. Accumulator should pass on next promise to 216 | * the accumulated value. 217 | * @param fn Accumulator that takes previous accumulation and current value, 218 | * and calculate next accumulation. 219 | * @param initial Initial accumulated value to start with. 220 | */ 221 | accumulate(fn: (U, T) => Promise, initial: U): ChainedPromise { 222 | let accumulated = initial; 223 | this.flatMap((v) => fn(accumulated, v)).map((acc) => { 224 | accumulated = acc; 225 | return acc; 226 | }); 227 | return ((this as any) as ChainedPromise); 228 | } 229 | 230 | /** 231 | * Takes a join spec and flatMaps current ChainedPromise accordingly. A join 232 | * spec is recursively defined as follows: 233 | * 234 | * * If the spec is a function taking a value and returning a promise, then 235 | * the join operation evaluates the function with current value and replaces 236 | * the value with the resulting promise. 237 | * 238 | * * If the spec is an array of a spec, then the current value is assumed to 239 | * be an array, and each element in the current value is mapped to the inner 240 | * spec. 241 | * 242 | * * If the spec is an object with keys to specs, then the field of the 243 | * current value with each key is replaced with the result of each join 244 | * operations with the inner spec. 245 | * @param {(function(T): (Promise.) | Array | Object)} spec 246 | * @returns {ChainedPromise.} 247 | * @template T 248 | * @template U 249 | * @template V 250 | */ 251 | join(spec: ((t: T) => Promise<{}>)|Array| 252 | Object): ChainedPromise { 253 | this.flatMap((v) => { 254 | function pickAndJoin(curSpec, curValue) { 255 | if (typeof curSpec === 'function') { 256 | return curSpec(curValue); 257 | } 258 | if (curSpec instanceof Array) { 259 | // TODO(yiinho): more thorough error handling. 260 | return Promise.all(curValue.map((x) => pickAndJoin(curSpec[0], x))); 261 | } 262 | if (curSpec instanceof Object) { 263 | return Promise 264 | .all(Object.keys(curSpec).map( 265 | (key) => pickAndJoin(curSpec[key], curValue[key]) 266 | .then((joinResult) => { 267 | const result = {}; 268 | result[key] = joinResult; 269 | return result; 270 | }))) 271 | .then((joinedValues) => { 272 | joinedValues.forEach((join) => Object.assign(curValue, join)); 273 | return curValue; 274 | }); 275 | } 276 | throw new TypeError( 277 | 'Specification not recognized: ' + JSON.stringify(spec)); 278 | } 279 | return pickAndJoin(spec, v); 280 | }); 281 | return this as any as ChainedPromise; 282 | } 283 | 284 | /** 285 | * Collects results (including the final "done" value) into an array. 286 | * @param fn Mapper function to be applied to each data points (except 287 | * the final "done" value) before collecting into the result array. 288 | */ 289 | collect(fn: (t: T) => (U | V) = (x) => (x as any as U)) { 290 | const collected: Array = []; 291 | return this 292 | .forEach((v) => { 293 | collected.push(fn(v)); 294 | }) 295 | .then((done) => { 296 | collected.push(done); 297 | return collected; 298 | }); 299 | } 300 | 301 | /** 302 | * Filters for values that evaluates to `true`. 303 | */ 304 | filter(fn: (t: T) => boolean): ChainedPromise> { 305 | return this.map>((v) => { 306 | if (!fn(v)) { 307 | return {data: ChainedPromise.SKIP, next: this.next(v)}; 308 | } 309 | return v; 310 | }); 311 | } 312 | 313 | /** 314 | * Symbol to indicate the end of promise chains. Having 315 | * `{[ChainedPromise.DONE]: }` as a next value will indicate the 316 | * end of the chain, and will cause fixed promises such as 317 | * {@link ChainedPromise#forEach} to resolve to the given value. 318 | */ 319 | static DONE = Symbol('ChainedPromise.DONE'); 320 | 321 | private static SKIP = Symbol('ChainedPromise.SKIP'); 322 | } 323 | 324 | export default ChainedPromise; 325 | -------------------------------------------------------------------------------- /test/ChainedPromise.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2017 Google Inc. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import ChainedPromise from '../src/index'; 17 | 18 | describe('ChainedPromise', function() { 19 | describe('createPromiseCallbackPair', function() { 20 | it('creates ChainedPromise and callback functions', function(done) { 21 | const dataCollected: Array = []; 22 | const [promise, callback] = 23 | ChainedPromise.createPromiseCallbackPair(); 24 | callback(1); 25 | callback(2); 26 | callback(3); 27 | promise 28 | .forEach((v) => { 29 | dataCollected.push(v.data); 30 | if (dataCollected.length === 3) { 31 | expect(dataCollected).toEqual([1, 2, 3]); 32 | done(); 33 | } 34 | }) 35 | .catch(done); 36 | }); 37 | }); 38 | it('creates error function which rejectes the promise', function(done) { 39 | const dataCollected: Array = []; 40 | const [promise, callback, error] = 41 | ChainedPromise.createPromiseCallbackPair(); 42 | callback(1); 43 | callback(2); 44 | error('Error!'); 45 | promise 46 | .forEach(({data}) => { 47 | dataCollected.push(data); 48 | }) 49 | .catch((err) => { 50 | expect(dataCollected).toEqual([1, 2]); 51 | expect(err).toEqual('Error!'); 52 | done(); 53 | }); 54 | }); 55 | describe('forEach', function() { 56 | it('runs function on each value', function(done) { 57 | const dataCollected: Array = []; 58 | const thirdPromise = 59 | Promise.resolve({data: 3, next: {[ChainedPromise.DONE]: 'done'}}); 60 | const secondPromise = Promise.resolve({data: 2, next: thirdPromise}); 61 | const testChainedPromise = 62 | new ChainedPromise<{data: number}>((resolver) => { 63 | resolver({data: 1, next: secondPromise}); 64 | }); 65 | testChainedPromise 66 | .forEach((v) => { 67 | dataCollected.push(v.data); 68 | }) 69 | .then((v) => { 70 | expect(v).toEqual('done'); 71 | expect(dataCollected).toEqual([1, 2, 3]); 72 | done(); 73 | }) 74 | .catch(done); 75 | }); 76 | }); 77 | it('bubbles up error', function(done) { 78 | const dataCollected: Array = []; 79 | const testChainedPromise = ChainedPromise.from(Promise.resolve({ 80 | data: 1, 81 | next: Promise.resolve({data: 2, next: Promise.reject('Error!')}) 82 | })); 83 | testChainedPromise 84 | .forEach(({data}) => { 85 | dataCollected.push(data); 86 | }) 87 | .catch((err) => { 88 | expect(dataCollected).toEqual([1, 2]); 89 | expect(err).toEqual('Error!'); 90 | done(); 91 | }); 92 | }); 93 | describe('flatMap', function() { 94 | it('composes flat map functions', function(done) { 95 | const addOnePromise = function(v) { 96 | return Promise.resolve(Object.assign(v, {data: v.data + 1})); 97 | }; 98 | const doublePromise = function(v) { 99 | return Promise.resolve(Object.assign(v, {data: v.data * 2})); 100 | }; 101 | const dataCollected: Array = []; 102 | const thirdPromise = 103 | Promise.resolve({data: 3, next: {[ChainedPromise.DONE]: 'done'}}); 104 | const secondPromise = Promise.resolve({data: 2, next: thirdPromise}); 105 | const testChainedPromise = new ChainedPromise((resolver) => { 106 | resolver({data: 1, next: secondPromise}); 107 | }); 108 | testChainedPromise.flatMap(addOnePromise) 109 | .flatMap(doublePromise) 110 | .forEach((v) => { 111 | dataCollected.push(v.data); 112 | }) 113 | .then((v) => { 114 | expect(v).toEqual('done'); 115 | expect(dataCollected).toEqual([4, 6, 8]); 116 | done(); 117 | }) 118 | .catch(done); 119 | }); 120 | }); 121 | describe('map', function() { 122 | it('composes map functions', function(done) { 123 | const addOneFunction = (v) => Object.assign(v, {data: v.data + 1}); 124 | const doubleFunction = (v) => Object.assign(v, {data: v.data * 2}); 125 | const dataCollected: Array = []; 126 | const thirdPromise = 127 | Promise.resolve({data: 3, next: {[ChainedPromise.DONE]: 'done'}}); 128 | const secondPromise = Promise.resolve({data: 2, next: thirdPromise}); 129 | const testChainedPromise = new ChainedPromise((resolver) => { 130 | resolver({data: 1, next: secondPromise}); 131 | }); 132 | testChainedPromise.map(addOneFunction) 133 | .map(doubleFunction) 134 | .forEach((v) => { 135 | dataCollected.push(v.data); 136 | }) 137 | .then((v) => { 138 | expect(v).toEqual('done'); 139 | expect(dataCollected).toEqual([4, 6, 8]); 140 | done(); 141 | }) 142 | .catch(done); 143 | }); 144 | }); 145 | describe('then', function() { 146 | it('bypasses composition when registering reject handler only', 147 | function(done) { 148 | const testChainedPromise = new ChainedPromise((resolver) => { 149 | resolver(1); 150 | }); 151 | testChainedPromise.flatMap((v) => Promise.resolve(v * 2)); 152 | testChainedPromise.then(undefined, console.error); 153 | testChainedPromise.then((v) => { 154 | expect(v).toEqual(2); // i.e. flatMapped function should have been 155 | // invoked only once. 156 | done(); 157 | }); 158 | }); 159 | }); 160 | describe('accumulate', function() { 161 | it('accumulates values', function(done) { 162 | const dataCollected: Array = []; 163 | const thirdPromise = 164 | Promise.resolve({data: 3, next: {[ChainedPromise.DONE]: 'done'}}); 165 | const secondPromise = Promise.resolve({data: 2, next: thirdPromise}); 166 | const testChainedPromise = new ChainedPromise((resolver) => { 167 | resolver({data: 1, next: secondPromise}); 168 | }); 169 | testChainedPromise 170 | .accumulate( 171 | (prevSum, newValue) => { 172 | return Promise.resolve(Object.assign( 173 | newValue, {data: prevSum.data + newValue.data})); 174 | }, 175 | {data: 0}) 176 | .forEach((v) => { 177 | dataCollected.push(v.data); 178 | }) 179 | .then((v) => { 180 | expect(v).toEqual('done'); 181 | expect(dataCollected).toEqual([1, 3, 6]); 182 | done(); 183 | }) 184 | .catch(done); 185 | }); 186 | }); 187 | describe('join', function() { 188 | it('extracts field', function(done) { 189 | type raw = {name: string, ref: number}; 190 | type joined = {name: string, ref: string}; 191 | const dataCollected: Array = []; 192 | const secondPromise = new ChainedPromise<{data: raw}>((resolver) => { 193 | resolver({ 194 | data: {name: 'Test Person 2', ref: 43}, 195 | next: {[ChainedPromise.DONE]: 'done'} 196 | }); 197 | }); 198 | const testChainedPromise = new ChainedPromise<{data: raw}>((resolver) => { 199 | resolver({data: {name: 'Test Person', ref: 42}, next: secondPromise}); 200 | }); 201 | testChainedPromise 202 | .join<{data: joined}>( 203 | {data: {ref: (v) => new Promise((res) => res('Reference ' + v))}}) 204 | .forEach((v) => { 205 | dataCollected.push(v.data); 206 | }) 207 | .then((v) => { 208 | expect(v).toEqual('done'); 209 | expect(dataCollected).toEqual([ 210 | {name: 'Test Person', ref: 'Reference 42'}, 211 | {name: 'Test Person 2', ref: 'Reference 43'} 212 | ]); 213 | done(); 214 | }) 215 | .catch(done); 216 | }); 217 | it('supports multiple fields', function(done) { 218 | type raw = {name: string, book: {ref: number}, car: {ref: number}}; 219 | type joined = {name: string, book: {ref: string}, car: {ref: string}}; 220 | const dataCollected: Array = []; 221 | const testChainedPromise = new ChainedPromise<{data: raw}>((resolver) => { 222 | resolver({ 223 | data: {name: 'Test Person', book: {ref: 42}, car: {ref: 43}}, 224 | next: {[ChainedPromise.DONE]: 'done'} 225 | }); 226 | }); 227 | testChainedPromise 228 | .join<{data: joined}>({ 229 | data: { 230 | book: { 231 | ref: (v) => new Promise((res) => res('Book reference ' + v)) 232 | }, 233 | car: { 234 | ref: (v) => new Promise((res) => res('Car reference ' + v)) 235 | } 236 | } 237 | }) 238 | .forEach((v) => { 239 | dataCollected.push(v.data); 240 | }) 241 | .then((v) => { 242 | expect(v).toEqual('done'); 243 | expect(dataCollected).toEqual([{ 244 | name: 'Test Person', 245 | book: {ref: 'Book reference 42'}, 246 | car: {ref: 'Car reference 43'} 247 | }]); 248 | done(); 249 | }) 250 | .catch(done); 251 | }); 252 | it('maps array of values', function(done) { 253 | type raw = {name: string, book: {ref: number}, car: {ref: number}}; 254 | type joined = {name: string, book: {ref: string}, car: {ref: string}}; 255 | const dataCollected: Array = []; 256 | const secondPromise = new ChainedPromise<{data: raw}>((resolver) => { 257 | resolver({ 258 | data: {name: 'Test Person 2', ref: [44, 45]}, 259 | next: {[ChainedPromise.DONE]: 'done'} 260 | }); 261 | }); 262 | const testChainedPromise = new ChainedPromise((resolver) => { 263 | resolver( 264 | {data: {name: 'Test Person', ref: [42, 43]}, next: secondPromise}); 265 | }); 266 | testChainedPromise 267 | .join<{data: joined}>({ 268 | data: {ref: [(v) => new Promise((res) => res('Reference ' + v))]} 269 | }) 270 | .forEach((v) => { 271 | dataCollected.push(v.data); 272 | }) 273 | .then((v) => { 274 | expect(v).toEqual('done'); 275 | expect(dataCollected).toEqual([ 276 | {name: 'Test Person', ref: ['Reference 42', 'Reference 43']}, 277 | {name: 'Test Person 2', ref: ['Reference 44', 'Reference 45']} 278 | ]); 279 | done(); 280 | }) 281 | .catch(done); 282 | }); 283 | it('supports object specification inside an array', function(done) { 284 | type raw = {name: string, book: [{ref: number}], car: [{ref: number}]}; 285 | type joined = {name: string, book: [{ref: string}], car: [{ref: string}]}; 286 | const dataCollected: Array = []; 287 | const secondPromise = new ChainedPromise((resolver) => { 288 | resolver({ 289 | data: {name: 'Test Person 2', refs: [{book: 44}, {book: 45}]}, 290 | next: {[ChainedPromise.DONE]: 'done'} 291 | }); 292 | }); 293 | const testChainedPromise = new ChainedPromise<{data: raw}>((resolver) => { 294 | resolver({ 295 | data: {name: 'Test Person', refs: [{book: 42}, {book: 43}]}, 296 | next: secondPromise 297 | }); 298 | }); 299 | testChainedPromise 300 | .join<{data: joined}>({ 301 | data: { 302 | refs: [ 303 | {book: (v) => new Promise((res) => res('Reference ' + v))} 304 | ] 305 | } 306 | }) 307 | .forEach((v) => { 308 | dataCollected.push(v.data); 309 | }) 310 | .then((v) => { 311 | expect(v).toEqual('done'); 312 | expect(dataCollected).toEqual([ 313 | { 314 | name: 'Test Person', 315 | refs: [{book: 'Reference 42'}, {book: 'Reference 43'}] 316 | }, 317 | { 318 | name: 'Test Person 2', 319 | refs: [{book: 'Reference 44'}, {book: 'Reference 45'}] 320 | } 321 | ]); 322 | done(); 323 | }) 324 | .catch(done); 325 | }); 326 | it('throws when the given spec is illegal', function(done) { 327 | const testChainedPromise = new ChainedPromise((resolver) => { 328 | resolver({ 329 | data: {name: 'Test Person', ref: 42}, 330 | next: {[ChainedPromise.DONE]: 'done'} 331 | }); 332 | }); 333 | testChainedPromise.join({data: {name: 'hello'}}) 334 | .then((v) => { 335 | done(v); 336 | }) 337 | .catch(() => { 338 | done(); 339 | }); 340 | }); 341 | }); 342 | describe('collect', function() { 343 | it('collects result in an array', function(done) { 344 | const thirdPromise = 345 | Promise.resolve({data: 3, next: {[ChainedPromise.DONE]: 'done'}}); 346 | const secondPromise = Promise.resolve({data: 2, next: thirdPromise}); 347 | const testChainedPromise = 348 | new ChainedPromise<{data: number}>((resolver) => { 349 | resolver({data: 1, next: secondPromise}); 350 | }); 351 | testChainedPromise.collect<{data: number}, string>() 352 | .then((result) => { 353 | expect((result[0] as {data: number}).data).toEqual(1); 354 | expect((result[1] as {data: number}).data).toEqual(2); 355 | expect((result[2] as {data: number}).data).toEqual(3); 356 | expect(result[3]).toEqual('done'); 357 | expect(result.length).toEqual(4); 358 | done(); 359 | }) 360 | .catch(done); 361 | }); 362 | it('transforms data before collecting into an array', function(done) { 363 | const thirdPromise = 364 | Promise.resolve({data: 3, next: {[ChainedPromise.DONE]: 'done'}}); 365 | const secondPromise = Promise.resolve({data: 2, next: thirdPromise}); 366 | const testChainedPromise = 367 | new ChainedPromise<{data: number}>((resolver) => { 368 | resolver({data: 1, next: secondPromise}); 369 | }); 370 | testChainedPromise.collect((v) => v.data) 371 | .then((result) => { 372 | expect(result).toEqual([1, 2, 3, 'done']); 373 | done(); 374 | }) 375 | .catch(done); 376 | }); 377 | }); 378 | describe('filter', () => { 379 | it('skips data', (done) => { 380 | const thirdPromise = 381 | Promise.resolve({data: 3, next: {[ChainedPromise.DONE]: 'done'}}); 382 | const secondPromise = Promise.resolve({data: 2, next: thirdPromise}); 383 | const testChainedPromise = 384 | new ChainedPromise<{data: number}>((resolver) => { 385 | resolver({data: 1, next: secondPromise}); 386 | }); 387 | testChainedPromise 388 | .map((v) => ({...v, data: v.data + 1})) // [2, 3, 4] 389 | .filter((v) => v.data % 2 == 0) // [2, 4] 390 | .map((v) => ({...v, data: v.data * 2})) // [4, 8] 391 | .collect<{data: number}, string>() 392 | .then((result) => { 393 | expect((result[0] as {data: number}).data).toEqual(4); 394 | expect((result[1] as {data: number}).data).toEqual(8); 395 | expect(result[2]).toEqual('done'); 396 | expect(result.length).toEqual(3); 397 | done(); 398 | }); 399 | }); 400 | }); 401 | }); 402 | -------------------------------------------------------------------------------- /examples/wikipedia-list-links/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wikipedia-list-links", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "8.0.46", 9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.46.tgz", 10 | "integrity": "sha512-rRkP4kb5JYIfAoRKaDbcdPZBcTNOgzSApyzhPN9e6rhViSJAWQGlSXIX5gc75iR02jikhpzy3usu31wMHllfFw==", 11 | "dev": true 12 | }, 13 | "@types/node-fetch": { 14 | "version": "1.6.7", 15 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-1.6.7.tgz", 16 | "integrity": "sha1-UhB46PDGmhWOUCIAWsqS0mIPbVc=", 17 | "dev": true, 18 | "requires": { 19 | "@types/node": "8.0.46" 20 | } 21 | }, 22 | "babel-polyfill": { 23 | "version": "6.26.0", 24 | "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", 25 | "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", 26 | "requires": { 27 | "babel-runtime": "6.26.0", 28 | "core-js": "2.5.1", 29 | "regenerator-runtime": "0.10.5" 30 | } 31 | }, 32 | "babel-runtime": { 33 | "version": "6.26.0", 34 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 35 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", 36 | "requires": { 37 | "core-js": "2.5.1", 38 | "regenerator-runtime": "0.11.0" 39 | }, 40 | "dependencies": { 41 | "regenerator-runtime": { 42 | "version": "0.11.0", 43 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", 44 | "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==" 45 | } 46 | } 47 | }, 48 | "chained-promise": { 49 | "version": "file:../..", 50 | "dependencies": { 51 | "@types/jest": { 52 | "version": "21.1.4", 53 | "bundled": true 54 | }, 55 | "abab": { 56 | "version": "1.0.4", 57 | "bundled": true 58 | }, 59 | "acorn": { 60 | "version": "4.0.13", 61 | "bundled": true 62 | }, 63 | "acorn-globals": { 64 | "version": "3.1.0", 65 | "bundled": true, 66 | "requires": { 67 | "acorn": "4.0.13" 68 | } 69 | }, 70 | "ajv": { 71 | "version": "5.2.5", 72 | "bundled": true, 73 | "requires": { 74 | "co": "4.6.0", 75 | "fast-deep-equal": "1.0.0", 76 | "json-schema-traverse": "0.3.1", 77 | "json-stable-stringify": "1.0.1" 78 | } 79 | }, 80 | "align-text": { 81 | "version": "0.1.4", 82 | "bundled": true, 83 | "requires": { 84 | "kind-of": "3.2.2", 85 | "longest": "1.0.1", 86 | "repeat-string": "1.6.1" 87 | } 88 | }, 89 | "amdefine": { 90 | "version": "1.0.1", 91 | "bundled": true 92 | }, 93 | "ansi-escapes": { 94 | "version": "3.0.0", 95 | "bundled": true 96 | }, 97 | "ansi-regex": { 98 | "version": "2.1.1", 99 | "bundled": true 100 | }, 101 | "ansi-styles": { 102 | "version": "3.2.0", 103 | "bundled": true, 104 | "requires": { 105 | "color-convert": "1.9.0" 106 | } 107 | }, 108 | "anymatch": { 109 | "version": "1.3.2", 110 | "bundled": true, 111 | "requires": { 112 | "micromatch": "2.3.11", 113 | "normalize-path": "2.1.1" 114 | } 115 | }, 116 | "append-transform": { 117 | "version": "0.4.0", 118 | "bundled": true, 119 | "requires": { 120 | "default-require-extensions": "1.0.0" 121 | } 122 | }, 123 | "argparse": { 124 | "version": "1.0.9", 125 | "bundled": true, 126 | "requires": { 127 | "sprintf-js": "1.0.3" 128 | } 129 | }, 130 | "arr-diff": { 131 | "version": "2.0.0", 132 | "bundled": true, 133 | "requires": { 134 | "arr-flatten": "1.1.0" 135 | } 136 | }, 137 | "arr-flatten": { 138 | "version": "1.1.0", 139 | "bundled": true 140 | }, 141 | "array-equal": { 142 | "version": "1.0.0", 143 | "bundled": true 144 | }, 145 | "array-unique": { 146 | "version": "0.2.1", 147 | "bundled": true 148 | }, 149 | "arrify": { 150 | "version": "1.0.1", 151 | "bundled": true 152 | }, 153 | "asn1": { 154 | "version": "0.2.3", 155 | "bundled": true 156 | }, 157 | "assert-plus": { 158 | "version": "1.0.0", 159 | "bundled": true 160 | }, 161 | "astral-regex": { 162 | "version": "1.0.0", 163 | "bundled": true 164 | }, 165 | "async": { 166 | "version": "2.5.0", 167 | "bundled": true, 168 | "requires": { 169 | "lodash": "4.17.4" 170 | } 171 | }, 172 | "asynckit": { 173 | "version": "0.4.0", 174 | "bundled": true 175 | }, 176 | "aws-sign2": { 177 | "version": "0.6.0", 178 | "bundled": true 179 | }, 180 | "aws4": { 181 | "version": "1.6.0", 182 | "bundled": true 183 | }, 184 | "babel-code-frame": { 185 | "version": "6.26.0", 186 | "bundled": true, 187 | "requires": { 188 | "chalk": "1.1.3", 189 | "esutils": "2.0.2", 190 | "js-tokens": "3.0.2" 191 | }, 192 | "dependencies": { 193 | "ansi-styles": { 194 | "version": "2.2.1", 195 | "bundled": true 196 | }, 197 | "chalk": { 198 | "version": "1.1.3", 199 | "bundled": true, 200 | "requires": { 201 | "ansi-styles": "2.2.1", 202 | "escape-string-regexp": "1.0.5", 203 | "has-ansi": "2.0.0", 204 | "strip-ansi": "3.0.1", 205 | "supports-color": "2.0.0" 206 | } 207 | }, 208 | "supports-color": { 209 | "version": "2.0.0", 210 | "bundled": true 211 | } 212 | } 213 | }, 214 | "babel-core": { 215 | "version": "6.26.0", 216 | "bundled": true, 217 | "requires": { 218 | "babel-code-frame": "6.26.0", 219 | "babel-generator": "6.26.0", 220 | "babel-helpers": "6.24.1", 221 | "babel-messages": "6.23.0", 222 | "babel-register": "6.26.0", 223 | "babel-runtime": "6.26.0", 224 | "babel-template": "6.26.0", 225 | "babel-traverse": "6.26.0", 226 | "babel-types": "6.26.0", 227 | "babylon": "6.18.0", 228 | "convert-source-map": "1.5.0", 229 | "debug": "2.6.9", 230 | "json5": "0.5.1", 231 | "lodash": "4.17.4", 232 | "minimatch": "3.0.4", 233 | "path-is-absolute": "1.0.1", 234 | "private": "0.1.8", 235 | "slash": "1.0.0", 236 | "source-map": "0.5.7" 237 | } 238 | }, 239 | "babel-generator": { 240 | "version": "6.26.0", 241 | "bundled": true, 242 | "requires": { 243 | "babel-messages": "6.23.0", 244 | "babel-runtime": "6.26.0", 245 | "babel-types": "6.26.0", 246 | "detect-indent": "4.0.0", 247 | "jsesc": "1.3.0", 248 | "lodash": "4.17.4", 249 | "source-map": "0.5.7", 250 | "trim-right": "1.0.1" 251 | } 252 | }, 253 | "babel-helpers": { 254 | "version": "6.24.1", 255 | "bundled": true, 256 | "requires": { 257 | "babel-runtime": "6.26.0", 258 | "babel-template": "6.26.0" 259 | } 260 | }, 261 | "babel-jest": { 262 | "version": "21.2.0", 263 | "bundled": true, 264 | "requires": { 265 | "babel-plugin-istanbul": "4.1.5", 266 | "babel-preset-jest": "21.2.0" 267 | } 268 | }, 269 | "babel-messages": { 270 | "version": "6.23.0", 271 | "bundled": true, 272 | "requires": { 273 | "babel-runtime": "6.26.0" 274 | } 275 | }, 276 | "babel-plugin-istanbul": { 277 | "version": "4.1.5", 278 | "bundled": true, 279 | "requires": { 280 | "find-up": "2.1.0", 281 | "istanbul-lib-instrument": "1.9.1", 282 | "test-exclude": "4.1.1" 283 | } 284 | }, 285 | "babel-plugin-jest-hoist": { 286 | "version": "21.2.0", 287 | "bundled": true 288 | }, 289 | "babel-plugin-syntax-object-rest-spread": { 290 | "version": "6.13.0", 291 | "bundled": true 292 | }, 293 | "babel-plugin-transform-es2015-modules-commonjs": { 294 | "version": "6.26.0", 295 | "bundled": true, 296 | "requires": { 297 | "babel-plugin-transform-strict-mode": "6.24.1", 298 | "babel-runtime": "6.26.0", 299 | "babel-template": "6.26.0", 300 | "babel-types": "6.26.0" 301 | } 302 | }, 303 | "babel-plugin-transform-strict-mode": { 304 | "version": "6.24.1", 305 | "bundled": true, 306 | "requires": { 307 | "babel-runtime": "6.26.0", 308 | "babel-types": "6.26.0" 309 | } 310 | }, 311 | "babel-preset-jest": { 312 | "version": "21.2.0", 313 | "bundled": true, 314 | "requires": { 315 | "babel-plugin-jest-hoist": "21.2.0", 316 | "babel-plugin-syntax-object-rest-spread": "6.13.0" 317 | } 318 | }, 319 | "babel-register": { 320 | "version": "6.26.0", 321 | "bundled": true, 322 | "requires": { 323 | "babel-core": "6.26.0", 324 | "babel-runtime": "6.26.0", 325 | "core-js": "2.5.1", 326 | "home-or-tmp": "2.0.0", 327 | "lodash": "4.17.4", 328 | "mkdirp": "0.5.1", 329 | "source-map-support": "0.4.18" 330 | }, 331 | "dependencies": { 332 | "source-map-support": { 333 | "version": "0.4.18", 334 | "bundled": true, 335 | "requires": { 336 | "source-map": "0.5.7" 337 | } 338 | } 339 | } 340 | }, 341 | "babel-runtime": { 342 | "version": "6.26.0", 343 | "bundled": true, 344 | "requires": { 345 | "core-js": "2.5.1", 346 | "regenerator-runtime": "0.11.0" 347 | } 348 | }, 349 | "babel-template": { 350 | "version": "6.26.0", 351 | "bundled": true, 352 | "requires": { 353 | "babel-runtime": "6.26.0", 354 | "babel-traverse": "6.26.0", 355 | "babel-types": "6.26.0", 356 | "babylon": "6.18.0", 357 | "lodash": "4.17.4" 358 | } 359 | }, 360 | "babel-traverse": { 361 | "version": "6.26.0", 362 | "bundled": true, 363 | "requires": { 364 | "babel-code-frame": "6.26.0", 365 | "babel-messages": "6.23.0", 366 | "babel-runtime": "6.26.0", 367 | "babel-types": "6.26.0", 368 | "babylon": "6.18.0", 369 | "debug": "2.6.9", 370 | "globals": "9.18.0", 371 | "invariant": "2.2.2", 372 | "lodash": "4.17.4" 373 | } 374 | }, 375 | "babel-types": { 376 | "version": "6.26.0", 377 | "bundled": true, 378 | "requires": { 379 | "babel-runtime": "6.26.0", 380 | "esutils": "2.0.2", 381 | "lodash": "4.17.4", 382 | "to-fast-properties": "1.0.3" 383 | } 384 | }, 385 | "babylon": { 386 | "version": "6.18.0", 387 | "bundled": true 388 | }, 389 | "balanced-match": { 390 | "version": "1.0.0", 391 | "bundled": true 392 | }, 393 | "bcrypt-pbkdf": { 394 | "version": "1.0.1", 395 | "bundled": true, 396 | "optional": true, 397 | "requires": { 398 | "tweetnacl": "0.14.5" 399 | } 400 | }, 401 | "bluebird": { 402 | "version": "3.5.1", 403 | "bundled": true 404 | }, 405 | "boom": { 406 | "version": "2.10.1", 407 | "bundled": true, 408 | "requires": { 409 | "hoek": "2.16.3" 410 | }, 411 | "dependencies": { 412 | "hoek": { 413 | "version": "2.16.3", 414 | "bundled": true 415 | } 416 | } 417 | }, 418 | "brace-expansion": { 419 | "version": "1.1.8", 420 | "bundled": true, 421 | "requires": { 422 | "balanced-match": "1.0.0", 423 | "concat-map": "0.0.1" 424 | } 425 | }, 426 | "braces": { 427 | "version": "1.8.5", 428 | "bundled": true, 429 | "requires": { 430 | "expand-range": "1.8.2", 431 | "preserve": "0.2.0", 432 | "repeat-element": "1.1.2" 433 | } 434 | }, 435 | "browser-resolve": { 436 | "version": "1.11.2", 437 | "bundled": true, 438 | "requires": { 439 | "resolve": "1.1.7" 440 | } 441 | }, 442 | "bser": { 443 | "version": "2.0.0", 444 | "bundled": true, 445 | "requires": { 446 | "node-int64": "0.4.0" 447 | } 448 | }, 449 | "builtin-modules": { 450 | "version": "1.1.1", 451 | "bundled": true 452 | }, 453 | "callsites": { 454 | "version": "2.0.0", 455 | "bundled": true 456 | }, 457 | "camelcase": { 458 | "version": "4.1.0", 459 | "bundled": true 460 | }, 461 | "caseless": { 462 | "version": "0.12.0", 463 | "bundled": true 464 | }, 465 | "catharsis": { 466 | "version": "0.8.9", 467 | "bundled": true, 468 | "requires": { 469 | "underscore-contrib": "0.3.0" 470 | } 471 | }, 472 | "center-align": { 473 | "version": "0.1.3", 474 | "bundled": true, 475 | "optional": true, 476 | "requires": { 477 | "align-text": "0.1.4", 478 | "lazy-cache": "1.0.4" 479 | } 480 | }, 481 | "chalk": { 482 | "version": "2.3.0", 483 | "bundled": true, 484 | "requires": { 485 | "ansi-styles": "3.2.0", 486 | "escape-string-regexp": "1.0.5", 487 | "supports-color": "4.5.0" 488 | } 489 | }, 490 | "ci-info": { 491 | "version": "1.1.1", 492 | "bundled": true 493 | }, 494 | "cliui": { 495 | "version": "3.2.0", 496 | "bundled": true, 497 | "requires": { 498 | "string-width": "1.0.2", 499 | "strip-ansi": "3.0.1", 500 | "wrap-ansi": "2.1.0" 501 | } 502 | }, 503 | "co": { 504 | "version": "4.6.0", 505 | "bundled": true 506 | }, 507 | "code-point-at": { 508 | "version": "1.1.0", 509 | "bundled": true 510 | }, 511 | "color-convert": { 512 | "version": "1.9.0", 513 | "bundled": true, 514 | "requires": { 515 | "color-name": "1.1.3" 516 | } 517 | }, 518 | "color-name": { 519 | "version": "1.1.3", 520 | "bundled": true 521 | }, 522 | "combined-stream": { 523 | "version": "1.0.5", 524 | "bundled": true, 525 | "requires": { 526 | "delayed-stream": "1.0.0" 527 | } 528 | }, 529 | "commander": { 530 | "version": "2.11.0", 531 | "bundled": true 532 | }, 533 | "concat-map": { 534 | "version": "0.0.1", 535 | "bundled": true 536 | }, 537 | "content-type-parser": { 538 | "version": "1.0.2", 539 | "bundled": true 540 | }, 541 | "convert-source-map": { 542 | "version": "1.5.0", 543 | "bundled": true 544 | }, 545 | "core-js": { 546 | "version": "2.5.1", 547 | "bundled": true 548 | }, 549 | "core-util-is": { 550 | "version": "1.0.2", 551 | "bundled": true 552 | }, 553 | "coveralls": { 554 | "version": "2.13.3", 555 | "bundled": true, 556 | "requires": { 557 | "js-yaml": "3.6.1", 558 | "lcov-parse": "0.0.10", 559 | "log-driver": "1.2.5", 560 | "minimist": "1.2.0", 561 | "request": "2.79.0" 562 | } 563 | }, 564 | "cross-spawn": { 565 | "version": "5.1.0", 566 | "bundled": true, 567 | "requires": { 568 | "lru-cache": "4.1.1", 569 | "shebang-command": "1.2.0", 570 | "which": "1.3.0" 571 | } 572 | }, 573 | "cryptiles": { 574 | "version": "2.0.5", 575 | "bundled": true, 576 | "requires": { 577 | "boom": "2.10.1" 578 | } 579 | }, 580 | "cssom": { 581 | "version": "0.3.2", 582 | "bundled": true 583 | }, 584 | "cssstyle": { 585 | "version": "0.2.37", 586 | "bundled": true, 587 | "requires": { 588 | "cssom": "0.3.2" 589 | } 590 | }, 591 | "dashdash": { 592 | "version": "1.14.1", 593 | "bundled": true, 594 | "requires": { 595 | "assert-plus": "1.0.0" 596 | } 597 | }, 598 | "debug": { 599 | "version": "2.6.9", 600 | "bundled": true, 601 | "requires": { 602 | "ms": "2.0.0" 603 | } 604 | }, 605 | "decamelize": { 606 | "version": "1.2.0", 607 | "bundled": true 608 | }, 609 | "deep-is": { 610 | "version": "0.1.3", 611 | "bundled": true 612 | }, 613 | "default-require-extensions": { 614 | "version": "1.0.0", 615 | "bundled": true, 616 | "requires": { 617 | "strip-bom": "2.0.0" 618 | } 619 | }, 620 | "delayed-stream": { 621 | "version": "1.0.0", 622 | "bundled": true 623 | }, 624 | "detect-indent": { 625 | "version": "4.0.0", 626 | "bundled": true, 627 | "requires": { 628 | "repeating": "2.0.1" 629 | } 630 | }, 631 | "diff": { 632 | "version": "3.4.0", 633 | "bundled": true 634 | }, 635 | "ecc-jsbn": { 636 | "version": "0.1.1", 637 | "bundled": true, 638 | "optional": true, 639 | "requires": { 640 | "jsbn": "0.1.1" 641 | } 642 | }, 643 | "errno": { 644 | "version": "0.1.4", 645 | "bundled": true, 646 | "requires": { 647 | "prr": "0.0.0" 648 | } 649 | }, 650 | "error-ex": { 651 | "version": "1.3.1", 652 | "bundled": true, 653 | "requires": { 654 | "is-arrayish": "0.2.1" 655 | } 656 | }, 657 | "escape-string-regexp": { 658 | "version": "1.0.5", 659 | "bundled": true 660 | }, 661 | "escodegen": { 662 | "version": "1.9.0", 663 | "bundled": true, 664 | "requires": { 665 | "esprima": "3.1.3", 666 | "estraverse": "4.2.0", 667 | "esutils": "2.0.2", 668 | "optionator": "0.8.2", 669 | "source-map": "0.5.7" 670 | }, 671 | "dependencies": { 672 | "esprima": { 673 | "version": "3.1.3", 674 | "bundled": true 675 | } 676 | } 677 | }, 678 | "esprima": { 679 | "version": "2.7.3", 680 | "bundled": true 681 | }, 682 | "estraverse": { 683 | "version": "4.2.0", 684 | "bundled": true 685 | }, 686 | "esutils": { 687 | "version": "2.0.2", 688 | "bundled": true 689 | }, 690 | "exec-sh": { 691 | "version": "0.2.1", 692 | "bundled": true, 693 | "requires": { 694 | "merge": "1.2.0" 695 | } 696 | }, 697 | "execa": { 698 | "version": "0.7.0", 699 | "bundled": true, 700 | "requires": { 701 | "cross-spawn": "5.1.0", 702 | "get-stream": "3.0.0", 703 | "is-stream": "1.1.0", 704 | "npm-run-path": "2.0.2", 705 | "p-finally": "1.0.0", 706 | "signal-exit": "3.0.2", 707 | "strip-eof": "1.0.0" 708 | } 709 | }, 710 | "expand-brackets": { 711 | "version": "0.1.5", 712 | "bundled": true, 713 | "requires": { 714 | "is-posix-bracket": "0.1.1" 715 | } 716 | }, 717 | "expand-range": { 718 | "version": "1.8.2", 719 | "bundled": true, 720 | "requires": { 721 | "fill-range": "2.2.3" 722 | } 723 | }, 724 | "expect": { 725 | "version": "21.2.1", 726 | "bundled": true, 727 | "requires": { 728 | "ansi-styles": "3.2.0", 729 | "jest-diff": "21.2.1", 730 | "jest-get-type": "21.2.0", 731 | "jest-matcher-utils": "21.2.1", 732 | "jest-message-util": "21.2.1", 733 | "jest-regex-util": "21.2.0" 734 | } 735 | }, 736 | "extend": { 737 | "version": "3.0.1", 738 | "bundled": true 739 | }, 740 | "extglob": { 741 | "version": "0.3.2", 742 | "bundled": true, 743 | "requires": { 744 | "is-extglob": "1.0.0" 745 | } 746 | }, 747 | "extsprintf": { 748 | "version": "1.3.0", 749 | "bundled": true 750 | }, 751 | "fast-deep-equal": { 752 | "version": "1.0.0", 753 | "bundled": true 754 | }, 755 | "fast-levenshtein": { 756 | "version": "2.0.6", 757 | "bundled": true 758 | }, 759 | "fb-watchman": { 760 | "version": "2.0.0", 761 | "bundled": true, 762 | "requires": { 763 | "bser": "2.0.0" 764 | } 765 | }, 766 | "filename-regex": { 767 | "version": "2.0.1", 768 | "bundled": true 769 | }, 770 | "fileset": { 771 | "version": "2.0.3", 772 | "bundled": true, 773 | "requires": { 774 | "glob": "7.1.2", 775 | "minimatch": "3.0.4" 776 | } 777 | }, 778 | "fill-range": { 779 | "version": "2.2.3", 780 | "bundled": true, 781 | "requires": { 782 | "is-number": "2.1.0", 783 | "isobject": "2.1.0", 784 | "randomatic": "1.1.7", 785 | "repeat-element": "1.1.2", 786 | "repeat-string": "1.6.1" 787 | } 788 | }, 789 | "find-up": { 790 | "version": "2.1.0", 791 | "bundled": true, 792 | "requires": { 793 | "locate-path": "2.0.0" 794 | } 795 | }, 796 | "for-in": { 797 | "version": "1.0.2", 798 | "bundled": true 799 | }, 800 | "for-own": { 801 | "version": "0.1.5", 802 | "bundled": true, 803 | "requires": { 804 | "for-in": "1.0.2" 805 | } 806 | }, 807 | "forever-agent": { 808 | "version": "0.6.1", 809 | "bundled": true 810 | }, 811 | "form-data": { 812 | "version": "2.1.4", 813 | "bundled": true, 814 | "requires": { 815 | "asynckit": "0.4.0", 816 | "combined-stream": "1.0.5", 817 | "mime-types": "2.1.17" 818 | } 819 | }, 820 | "fs-extra": { 821 | "version": "4.0.2", 822 | "bundled": true, 823 | "requires": { 824 | "graceful-fs": "4.1.11", 825 | "jsonfile": "4.0.0", 826 | "universalify": "0.1.1" 827 | } 828 | }, 829 | "fs.realpath": { 830 | "version": "1.0.0", 831 | "bundled": true 832 | }, 833 | "generate-function": { 834 | "version": "2.0.0", 835 | "bundled": true 836 | }, 837 | "generate-object-property": { 838 | "version": "1.2.0", 839 | "bundled": true, 840 | "requires": { 841 | "is-property": "1.0.2" 842 | } 843 | }, 844 | "get-caller-file": { 845 | "version": "1.0.2", 846 | "bundled": true 847 | }, 848 | "get-stream": { 849 | "version": "3.0.0", 850 | "bundled": true 851 | }, 852 | "getpass": { 853 | "version": "0.1.7", 854 | "bundled": true, 855 | "requires": { 856 | "assert-plus": "1.0.0" 857 | } 858 | }, 859 | "glob": { 860 | "version": "7.1.2", 861 | "bundled": true, 862 | "requires": { 863 | "fs.realpath": "1.0.0", 864 | "inflight": "1.0.6", 865 | "inherits": "2.0.3", 866 | "minimatch": "3.0.4", 867 | "once": "1.4.0", 868 | "path-is-absolute": "1.0.1" 869 | } 870 | }, 871 | "glob-base": { 872 | "version": "0.3.0", 873 | "bundled": true, 874 | "requires": { 875 | "glob-parent": "2.0.0", 876 | "is-glob": "2.0.1" 877 | } 878 | }, 879 | "glob-parent": { 880 | "version": "2.0.0", 881 | "bundled": true, 882 | "requires": { 883 | "is-glob": "2.0.1" 884 | } 885 | }, 886 | "globals": { 887 | "version": "9.18.0", 888 | "bundled": true 889 | }, 890 | "graceful-fs": { 891 | "version": "4.1.11", 892 | "bundled": true 893 | }, 894 | "growly": { 895 | "version": "1.3.0", 896 | "bundled": true 897 | }, 898 | "handlebars": { 899 | "version": "4.0.11", 900 | "bundled": true, 901 | "requires": { 902 | "async": "1.5.2", 903 | "optimist": "0.6.1", 904 | "source-map": "0.4.4", 905 | "uglify-js": "2.8.29" 906 | }, 907 | "dependencies": { 908 | "async": { 909 | "version": "1.5.2", 910 | "bundled": true 911 | }, 912 | "source-map": { 913 | "version": "0.4.4", 914 | "bundled": true, 915 | "requires": { 916 | "amdefine": "1.0.1" 917 | } 918 | } 919 | } 920 | }, 921 | "har-schema": { 922 | "version": "2.0.0", 923 | "bundled": true 924 | }, 925 | "har-validator": { 926 | "version": "2.0.6", 927 | "bundled": true, 928 | "requires": { 929 | "chalk": "1.1.3", 930 | "commander": "2.11.0", 931 | "is-my-json-valid": "2.16.1", 932 | "pinkie-promise": "2.0.1" 933 | }, 934 | "dependencies": { 935 | "ansi-styles": { 936 | "version": "2.2.1", 937 | "bundled": true 938 | }, 939 | "chalk": { 940 | "version": "1.1.3", 941 | "bundled": true, 942 | "requires": { 943 | "ansi-styles": "2.2.1", 944 | "escape-string-regexp": "1.0.5", 945 | "has-ansi": "2.0.0", 946 | "strip-ansi": "3.0.1", 947 | "supports-color": "2.0.0" 948 | } 949 | }, 950 | "supports-color": { 951 | "version": "2.0.0", 952 | "bundled": true 953 | } 954 | } 955 | }, 956 | "has-ansi": { 957 | "version": "2.0.0", 958 | "bundled": true, 959 | "requires": { 960 | "ansi-regex": "2.1.1" 961 | } 962 | }, 963 | "has-flag": { 964 | "version": "2.0.0", 965 | "bundled": true 966 | }, 967 | "hawk": { 968 | "version": "3.1.3", 969 | "bundled": true, 970 | "requires": { 971 | "boom": "2.10.1", 972 | "cryptiles": "2.0.5", 973 | "hoek": "2.16.3", 974 | "sntp": "1.0.9" 975 | }, 976 | "dependencies": { 977 | "hoek": { 978 | "version": "2.16.3", 979 | "bundled": true 980 | } 981 | } 982 | }, 983 | "hoek": { 984 | "version": "4.2.0", 985 | "bundled": true 986 | }, 987 | "home-or-tmp": { 988 | "version": "2.0.0", 989 | "bundled": true, 990 | "requires": { 991 | "os-homedir": "1.0.2", 992 | "os-tmpdir": "1.0.2" 993 | } 994 | }, 995 | "hosted-git-info": { 996 | "version": "2.5.0", 997 | "bundled": true 998 | }, 999 | "html-encoding-sniffer": { 1000 | "version": "1.0.2", 1001 | "bundled": true, 1002 | "requires": { 1003 | "whatwg-encoding": "1.0.2" 1004 | } 1005 | }, 1006 | "http-signature": { 1007 | "version": "1.1.1", 1008 | "bundled": true, 1009 | "requires": { 1010 | "assert-plus": "0.2.0", 1011 | "jsprim": "1.4.1", 1012 | "sshpk": "1.13.1" 1013 | }, 1014 | "dependencies": { 1015 | "assert-plus": { 1016 | "version": "0.2.0", 1017 | "bundled": true 1018 | } 1019 | } 1020 | }, 1021 | "iconv-lite": { 1022 | "version": "0.4.13", 1023 | "bundled": true 1024 | }, 1025 | "imurmurhash": { 1026 | "version": "0.1.4", 1027 | "bundled": true 1028 | }, 1029 | "inflight": { 1030 | "version": "1.0.6", 1031 | "bundled": true, 1032 | "requires": { 1033 | "once": "1.4.0", 1034 | "wrappy": "1.0.2" 1035 | } 1036 | }, 1037 | "inherits": { 1038 | "version": "2.0.3", 1039 | "bundled": true 1040 | }, 1041 | "invariant": { 1042 | "version": "2.2.2", 1043 | "bundled": true, 1044 | "requires": { 1045 | "loose-envify": "1.3.1" 1046 | } 1047 | }, 1048 | "invert-kv": { 1049 | "version": "1.0.0", 1050 | "bundled": true 1051 | }, 1052 | "is-arrayish": { 1053 | "version": "0.2.1", 1054 | "bundled": true 1055 | }, 1056 | "is-buffer": { 1057 | "version": "1.1.5", 1058 | "bundled": true 1059 | }, 1060 | "is-builtin-module": { 1061 | "version": "1.0.0", 1062 | "bundled": true, 1063 | "requires": { 1064 | "builtin-modules": "1.1.1" 1065 | } 1066 | }, 1067 | "is-ci": { 1068 | "version": "1.0.10", 1069 | "bundled": true, 1070 | "requires": { 1071 | "ci-info": "1.1.1" 1072 | } 1073 | }, 1074 | "is-dotfile": { 1075 | "version": "1.0.3", 1076 | "bundled": true 1077 | }, 1078 | "is-equal-shallow": { 1079 | "version": "0.1.3", 1080 | "bundled": true, 1081 | "requires": { 1082 | "is-primitive": "2.0.0" 1083 | } 1084 | }, 1085 | "is-extendable": { 1086 | "version": "0.1.1", 1087 | "bundled": true 1088 | }, 1089 | "is-extglob": { 1090 | "version": "1.0.0", 1091 | "bundled": true 1092 | }, 1093 | "is-finite": { 1094 | "version": "1.0.2", 1095 | "bundled": true, 1096 | "requires": { 1097 | "number-is-nan": "1.0.1" 1098 | } 1099 | }, 1100 | "is-fullwidth-code-point": { 1101 | "version": "1.0.0", 1102 | "bundled": true, 1103 | "requires": { 1104 | "number-is-nan": "1.0.1" 1105 | } 1106 | }, 1107 | "is-glob": { 1108 | "version": "2.0.1", 1109 | "bundled": true, 1110 | "requires": { 1111 | "is-extglob": "1.0.0" 1112 | } 1113 | }, 1114 | "is-my-json-valid": { 1115 | "version": "2.16.1", 1116 | "bundled": true, 1117 | "requires": { 1118 | "generate-function": "2.0.0", 1119 | "generate-object-property": "1.2.0", 1120 | "jsonpointer": "4.0.1", 1121 | "xtend": "4.0.1" 1122 | } 1123 | }, 1124 | "is-number": { 1125 | "version": "2.1.0", 1126 | "bundled": true, 1127 | "requires": { 1128 | "kind-of": "3.2.2" 1129 | } 1130 | }, 1131 | "is-posix-bracket": { 1132 | "version": "0.1.1", 1133 | "bundled": true 1134 | }, 1135 | "is-primitive": { 1136 | "version": "2.0.0", 1137 | "bundled": true 1138 | }, 1139 | "is-property": { 1140 | "version": "1.0.2", 1141 | "bundled": true 1142 | }, 1143 | "is-stream": { 1144 | "version": "1.1.0", 1145 | "bundled": true 1146 | }, 1147 | "is-typedarray": { 1148 | "version": "1.0.0", 1149 | "bundled": true 1150 | }, 1151 | "is-utf8": { 1152 | "version": "0.2.1", 1153 | "bundled": true 1154 | }, 1155 | "isarray": { 1156 | "version": "1.0.0", 1157 | "bundled": true 1158 | }, 1159 | "isexe": { 1160 | "version": "2.0.0", 1161 | "bundled": true 1162 | }, 1163 | "isobject": { 1164 | "version": "2.1.0", 1165 | "bundled": true, 1166 | "requires": { 1167 | "isarray": "1.0.0" 1168 | } 1169 | }, 1170 | "isstream": { 1171 | "version": "0.1.2", 1172 | "bundled": true 1173 | }, 1174 | "istanbul-api": { 1175 | "version": "1.2.1", 1176 | "bundled": true, 1177 | "requires": { 1178 | "async": "2.5.0", 1179 | "fileset": "2.0.3", 1180 | "istanbul-lib-coverage": "1.1.1", 1181 | "istanbul-lib-hook": "1.1.0", 1182 | "istanbul-lib-instrument": "1.9.1", 1183 | "istanbul-lib-report": "1.1.2", 1184 | "istanbul-lib-source-maps": "1.2.2", 1185 | "istanbul-reports": "1.1.3", 1186 | "js-yaml": "3.10.0", 1187 | "mkdirp": "0.5.1", 1188 | "once": "1.4.0" 1189 | }, 1190 | "dependencies": { 1191 | "esprima": { 1192 | "version": "4.0.0", 1193 | "bundled": true 1194 | }, 1195 | "js-yaml": { 1196 | "version": "3.10.0", 1197 | "bundled": true, 1198 | "requires": { 1199 | "argparse": "1.0.9", 1200 | "esprima": "4.0.0" 1201 | } 1202 | } 1203 | } 1204 | }, 1205 | "istanbul-lib-coverage": { 1206 | "version": "1.1.1", 1207 | "bundled": true 1208 | }, 1209 | "istanbul-lib-hook": { 1210 | "version": "1.1.0", 1211 | "bundled": true, 1212 | "requires": { 1213 | "append-transform": "0.4.0" 1214 | } 1215 | }, 1216 | "istanbul-lib-instrument": { 1217 | "version": "1.9.1", 1218 | "bundled": true, 1219 | "requires": { 1220 | "babel-generator": "6.26.0", 1221 | "babel-template": "6.26.0", 1222 | "babel-traverse": "6.26.0", 1223 | "babel-types": "6.26.0", 1224 | "babylon": "6.18.0", 1225 | "istanbul-lib-coverage": "1.1.1", 1226 | "semver": "5.4.1" 1227 | } 1228 | }, 1229 | "istanbul-lib-report": { 1230 | "version": "1.1.2", 1231 | "bundled": true, 1232 | "requires": { 1233 | "istanbul-lib-coverage": "1.1.1", 1234 | "mkdirp": "0.5.1", 1235 | "path-parse": "1.0.5", 1236 | "supports-color": "3.2.3" 1237 | }, 1238 | "dependencies": { 1239 | "has-flag": { 1240 | "version": "1.0.0", 1241 | "bundled": true 1242 | }, 1243 | "supports-color": { 1244 | "version": "3.2.3", 1245 | "bundled": true, 1246 | "requires": { 1247 | "has-flag": "1.0.0" 1248 | } 1249 | } 1250 | } 1251 | }, 1252 | "istanbul-lib-source-maps": { 1253 | "version": "1.2.2", 1254 | "bundled": true, 1255 | "requires": { 1256 | "debug": "3.1.0", 1257 | "istanbul-lib-coverage": "1.1.1", 1258 | "mkdirp": "0.5.1", 1259 | "rimraf": "2.6.2", 1260 | "source-map": "0.5.7" 1261 | }, 1262 | "dependencies": { 1263 | "debug": { 1264 | "version": "3.1.0", 1265 | "bundled": true, 1266 | "requires": { 1267 | "ms": "2.0.0" 1268 | } 1269 | } 1270 | } 1271 | }, 1272 | "istanbul-reports": { 1273 | "version": "1.1.3", 1274 | "bundled": true, 1275 | "requires": { 1276 | "handlebars": "4.0.11" 1277 | } 1278 | }, 1279 | "jest": { 1280 | "version": "21.2.1", 1281 | "bundled": true, 1282 | "requires": { 1283 | "jest-cli": "21.2.1" 1284 | } 1285 | }, 1286 | "jest-changed-files": { 1287 | "version": "21.2.0", 1288 | "bundled": true, 1289 | "requires": { 1290 | "throat": "4.1.0" 1291 | } 1292 | }, 1293 | "jest-cli": { 1294 | "version": "21.2.1", 1295 | "bundled": true, 1296 | "requires": { 1297 | "ansi-escapes": "3.0.0", 1298 | "chalk": "2.3.0", 1299 | "glob": "7.1.2", 1300 | "graceful-fs": "4.1.11", 1301 | "is-ci": "1.0.10", 1302 | "istanbul-api": "1.2.1", 1303 | "istanbul-lib-coverage": "1.1.1", 1304 | "istanbul-lib-instrument": "1.9.1", 1305 | "istanbul-lib-source-maps": "1.2.2", 1306 | "jest-changed-files": "21.2.0", 1307 | "jest-config": "21.2.1", 1308 | "jest-environment-jsdom": "21.2.1", 1309 | "jest-haste-map": "21.2.0", 1310 | "jest-message-util": "21.2.1", 1311 | "jest-regex-util": "21.2.0", 1312 | "jest-resolve-dependencies": "21.2.0", 1313 | "jest-runner": "21.2.1", 1314 | "jest-runtime": "21.2.1", 1315 | "jest-snapshot": "21.2.1", 1316 | "jest-util": "21.2.1", 1317 | "micromatch": "2.3.11", 1318 | "node-notifier": "5.1.2", 1319 | "pify": "3.0.0", 1320 | "slash": "1.0.0", 1321 | "string-length": "2.0.0", 1322 | "strip-ansi": "4.0.0", 1323 | "which": "1.3.0", 1324 | "worker-farm": "1.5.0", 1325 | "yargs": "9.0.1" 1326 | }, 1327 | "dependencies": { 1328 | "ansi-regex": { 1329 | "version": "3.0.0", 1330 | "bundled": true 1331 | }, 1332 | "pify": { 1333 | "version": "3.0.0", 1334 | "bundled": true 1335 | }, 1336 | "strip-ansi": { 1337 | "version": "4.0.0", 1338 | "bundled": true, 1339 | "requires": { 1340 | "ansi-regex": "3.0.0" 1341 | } 1342 | } 1343 | } 1344 | }, 1345 | "jest-config": { 1346 | "version": "21.2.1", 1347 | "bundled": true, 1348 | "requires": { 1349 | "chalk": "2.3.0", 1350 | "glob": "7.1.2", 1351 | "jest-environment-jsdom": "21.2.1", 1352 | "jest-environment-node": "21.2.1", 1353 | "jest-get-type": "21.2.0", 1354 | "jest-jasmine2": "21.2.1", 1355 | "jest-regex-util": "21.2.0", 1356 | "jest-resolve": "21.2.0", 1357 | "jest-util": "21.2.1", 1358 | "jest-validate": "21.2.1", 1359 | "pretty-format": "21.2.1" 1360 | } 1361 | }, 1362 | "jest-diff": { 1363 | "version": "21.2.1", 1364 | "bundled": true, 1365 | "requires": { 1366 | "chalk": "2.3.0", 1367 | "diff": "3.4.0", 1368 | "jest-get-type": "21.2.0", 1369 | "pretty-format": "21.2.1" 1370 | } 1371 | }, 1372 | "jest-docblock": { 1373 | "version": "21.2.0", 1374 | "bundled": true 1375 | }, 1376 | "jest-environment-jsdom": { 1377 | "version": "21.2.1", 1378 | "bundled": true, 1379 | "requires": { 1380 | "jest-mock": "21.2.0", 1381 | "jest-util": "21.2.1", 1382 | "jsdom": "9.12.0" 1383 | } 1384 | }, 1385 | "jest-environment-node": { 1386 | "version": "21.2.1", 1387 | "bundled": true, 1388 | "requires": { 1389 | "jest-mock": "21.2.0", 1390 | "jest-util": "21.2.1" 1391 | } 1392 | }, 1393 | "jest-get-type": { 1394 | "version": "21.2.0", 1395 | "bundled": true 1396 | }, 1397 | "jest-haste-map": { 1398 | "version": "21.2.0", 1399 | "bundled": true, 1400 | "requires": { 1401 | "fb-watchman": "2.0.0", 1402 | "graceful-fs": "4.1.11", 1403 | "jest-docblock": "21.2.0", 1404 | "micromatch": "2.3.11", 1405 | "sane": "2.2.0", 1406 | "worker-farm": "1.5.0" 1407 | } 1408 | }, 1409 | "jest-jasmine2": { 1410 | "version": "21.2.1", 1411 | "bundled": true, 1412 | "requires": { 1413 | "chalk": "2.3.0", 1414 | "expect": "21.2.1", 1415 | "graceful-fs": "4.1.11", 1416 | "jest-diff": "21.2.1", 1417 | "jest-matcher-utils": "21.2.1", 1418 | "jest-message-util": "21.2.1", 1419 | "jest-snapshot": "21.2.1", 1420 | "p-cancelable": "0.3.0" 1421 | } 1422 | }, 1423 | "jest-matcher-utils": { 1424 | "version": "21.2.1", 1425 | "bundled": true, 1426 | "requires": { 1427 | "chalk": "2.3.0", 1428 | "jest-get-type": "21.2.0", 1429 | "pretty-format": "21.2.1" 1430 | } 1431 | }, 1432 | "jest-message-util": { 1433 | "version": "21.2.1", 1434 | "bundled": true, 1435 | "requires": { 1436 | "chalk": "2.3.0", 1437 | "micromatch": "2.3.11", 1438 | "slash": "1.0.0" 1439 | } 1440 | }, 1441 | "jest-mock": { 1442 | "version": "21.2.0", 1443 | "bundled": true 1444 | }, 1445 | "jest-regex-util": { 1446 | "version": "21.2.0", 1447 | "bundled": true 1448 | }, 1449 | "jest-resolve": { 1450 | "version": "21.2.0", 1451 | "bundled": true, 1452 | "requires": { 1453 | "browser-resolve": "1.11.2", 1454 | "chalk": "2.3.0", 1455 | "is-builtin-module": "1.0.0" 1456 | } 1457 | }, 1458 | "jest-resolve-dependencies": { 1459 | "version": "21.2.0", 1460 | "bundled": true, 1461 | "requires": { 1462 | "jest-regex-util": "21.2.0" 1463 | } 1464 | }, 1465 | "jest-runner": { 1466 | "version": "21.2.1", 1467 | "bundled": true, 1468 | "requires": { 1469 | "jest-config": "21.2.1", 1470 | "jest-docblock": "21.2.0", 1471 | "jest-haste-map": "21.2.0", 1472 | "jest-jasmine2": "21.2.1", 1473 | "jest-message-util": "21.2.1", 1474 | "jest-runtime": "21.2.1", 1475 | "jest-util": "21.2.1", 1476 | "pify": "3.0.0", 1477 | "throat": "4.1.0", 1478 | "worker-farm": "1.5.0" 1479 | }, 1480 | "dependencies": { 1481 | "pify": { 1482 | "version": "3.0.0", 1483 | "bundled": true 1484 | } 1485 | } 1486 | }, 1487 | "jest-runtime": { 1488 | "version": "21.2.1", 1489 | "bundled": true, 1490 | "requires": { 1491 | "babel-core": "6.26.0", 1492 | "babel-jest": "21.2.0", 1493 | "babel-plugin-istanbul": "4.1.5", 1494 | "chalk": "2.3.0", 1495 | "convert-source-map": "1.5.0", 1496 | "graceful-fs": "4.1.11", 1497 | "jest-config": "21.2.1", 1498 | "jest-haste-map": "21.2.0", 1499 | "jest-regex-util": "21.2.0", 1500 | "jest-resolve": "21.2.0", 1501 | "jest-util": "21.2.1", 1502 | "json-stable-stringify": "1.0.1", 1503 | "micromatch": "2.3.11", 1504 | "slash": "1.0.0", 1505 | "strip-bom": "3.0.0", 1506 | "write-file-atomic": "2.3.0", 1507 | "yargs": "9.0.1" 1508 | }, 1509 | "dependencies": { 1510 | "strip-bom": { 1511 | "version": "3.0.0", 1512 | "bundled": true 1513 | } 1514 | } 1515 | }, 1516 | "jest-snapshot": { 1517 | "version": "21.2.1", 1518 | "bundled": true, 1519 | "requires": { 1520 | "chalk": "2.3.0", 1521 | "jest-diff": "21.2.1", 1522 | "jest-matcher-utils": "21.2.1", 1523 | "mkdirp": "0.5.1", 1524 | "natural-compare": "1.4.0", 1525 | "pretty-format": "21.2.1" 1526 | } 1527 | }, 1528 | "jest-util": { 1529 | "version": "21.2.1", 1530 | "bundled": true, 1531 | "requires": { 1532 | "callsites": "2.0.0", 1533 | "chalk": "2.3.0", 1534 | "graceful-fs": "4.1.11", 1535 | "jest-message-util": "21.2.1", 1536 | "jest-mock": "21.2.0", 1537 | "jest-validate": "21.2.1", 1538 | "mkdirp": "0.5.1" 1539 | } 1540 | }, 1541 | "jest-validate": { 1542 | "version": "21.2.1", 1543 | "bundled": true, 1544 | "requires": { 1545 | "chalk": "2.3.0", 1546 | "jest-get-type": "21.2.0", 1547 | "leven": "2.1.0", 1548 | "pretty-format": "21.2.1" 1549 | } 1550 | }, 1551 | "js-tokens": { 1552 | "version": "3.0.2", 1553 | "bundled": true 1554 | }, 1555 | "js-yaml": { 1556 | "version": "3.6.1", 1557 | "bundled": true, 1558 | "requires": { 1559 | "argparse": "1.0.9", 1560 | "esprima": "2.7.3" 1561 | } 1562 | }, 1563 | "js2xmlparser": { 1564 | "version": "3.0.0", 1565 | "bundled": true, 1566 | "requires": { 1567 | "xmlcreate": "1.0.2" 1568 | } 1569 | }, 1570 | "jsbn": { 1571 | "version": "0.1.1", 1572 | "bundled": true, 1573 | "optional": true 1574 | }, 1575 | "jsdoc": { 1576 | "version": "3.5.5", 1577 | "bundled": true, 1578 | "requires": { 1579 | "babylon": "7.0.0-beta.19", 1580 | "bluebird": "3.5.1", 1581 | "catharsis": "0.8.9", 1582 | "escape-string-regexp": "1.0.5", 1583 | "js2xmlparser": "3.0.0", 1584 | "klaw": "2.0.0", 1585 | "marked": "0.3.6", 1586 | "mkdirp": "0.5.1", 1587 | "requizzle": "0.2.1", 1588 | "strip-json-comments": "2.0.1", 1589 | "taffydb": "2.6.2", 1590 | "underscore": "1.8.3" 1591 | }, 1592 | "dependencies": { 1593 | "babylon": { 1594 | "version": "7.0.0-beta.19", 1595 | "bundled": true 1596 | }, 1597 | "underscore": { 1598 | "version": "1.8.3", 1599 | "bundled": true 1600 | } 1601 | } 1602 | }, 1603 | "jsdom": { 1604 | "version": "9.12.0", 1605 | "bundled": true, 1606 | "requires": { 1607 | "abab": "1.0.4", 1608 | "acorn": "4.0.13", 1609 | "acorn-globals": "3.1.0", 1610 | "array-equal": "1.0.0", 1611 | "content-type-parser": "1.0.2", 1612 | "cssom": "0.3.2", 1613 | "cssstyle": "0.2.37", 1614 | "escodegen": "1.9.0", 1615 | "html-encoding-sniffer": "1.0.2", 1616 | "nwmatcher": "1.4.3", 1617 | "parse5": "1.5.1", 1618 | "request": "2.83.0", 1619 | "sax": "1.2.4", 1620 | "symbol-tree": "3.2.2", 1621 | "tough-cookie": "2.3.3", 1622 | "webidl-conversions": "4.0.2", 1623 | "whatwg-encoding": "1.0.2", 1624 | "whatwg-url": "4.8.0", 1625 | "xml-name-validator": "2.0.1" 1626 | }, 1627 | "dependencies": { 1628 | "aws-sign2": { 1629 | "version": "0.7.0", 1630 | "bundled": true 1631 | }, 1632 | "boom": { 1633 | "version": "4.3.1", 1634 | "bundled": true, 1635 | "requires": { 1636 | "hoek": "4.2.0" 1637 | } 1638 | }, 1639 | "cryptiles": { 1640 | "version": "3.1.2", 1641 | "bundled": true, 1642 | "requires": { 1643 | "boom": "5.2.0" 1644 | }, 1645 | "dependencies": { 1646 | "boom": { 1647 | "version": "5.2.0", 1648 | "bundled": true, 1649 | "requires": { 1650 | "hoek": "4.2.0" 1651 | } 1652 | } 1653 | } 1654 | }, 1655 | "form-data": { 1656 | "version": "2.3.1", 1657 | "bundled": true, 1658 | "requires": { 1659 | "asynckit": "0.4.0", 1660 | "combined-stream": "1.0.5", 1661 | "mime-types": "2.1.17" 1662 | } 1663 | }, 1664 | "har-validator": { 1665 | "version": "5.0.3", 1666 | "bundled": true, 1667 | "requires": { 1668 | "ajv": "5.2.5", 1669 | "har-schema": "2.0.0" 1670 | } 1671 | }, 1672 | "hawk": { 1673 | "version": "6.0.2", 1674 | "bundled": true, 1675 | "requires": { 1676 | "boom": "4.3.1", 1677 | "cryptiles": "3.1.2", 1678 | "hoek": "4.2.0", 1679 | "sntp": "2.0.2" 1680 | } 1681 | }, 1682 | "http-signature": { 1683 | "version": "1.2.0", 1684 | "bundled": true, 1685 | "requires": { 1686 | "assert-plus": "1.0.0", 1687 | "jsprim": "1.4.1", 1688 | "sshpk": "1.13.1" 1689 | } 1690 | }, 1691 | "qs": { 1692 | "version": "6.5.1", 1693 | "bundled": true 1694 | }, 1695 | "request": { 1696 | "version": "2.83.0", 1697 | "bundled": true, 1698 | "requires": { 1699 | "aws-sign2": "0.7.0", 1700 | "aws4": "1.6.0", 1701 | "caseless": "0.12.0", 1702 | "combined-stream": "1.0.5", 1703 | "extend": "3.0.1", 1704 | "forever-agent": "0.6.1", 1705 | "form-data": "2.3.1", 1706 | "har-validator": "5.0.3", 1707 | "hawk": "6.0.2", 1708 | "http-signature": "1.2.0", 1709 | "is-typedarray": "1.0.0", 1710 | "isstream": "0.1.2", 1711 | "json-stringify-safe": "5.0.1", 1712 | "mime-types": "2.1.17", 1713 | "oauth-sign": "0.8.2", 1714 | "performance-now": "2.1.0", 1715 | "qs": "6.5.1", 1716 | "safe-buffer": "5.1.1", 1717 | "stringstream": "0.0.5", 1718 | "tough-cookie": "2.3.3", 1719 | "tunnel-agent": "0.6.0", 1720 | "uuid": "3.1.0" 1721 | } 1722 | }, 1723 | "sntp": { 1724 | "version": "2.0.2", 1725 | "bundled": true, 1726 | "requires": { 1727 | "hoek": "4.2.0" 1728 | } 1729 | } 1730 | } 1731 | }, 1732 | "jsesc": { 1733 | "version": "1.3.0", 1734 | "bundled": true 1735 | }, 1736 | "json-schema": { 1737 | "version": "0.2.3", 1738 | "bundled": true 1739 | }, 1740 | "json-schema-traverse": { 1741 | "version": "0.3.1", 1742 | "bundled": true 1743 | }, 1744 | "json-stable-stringify": { 1745 | "version": "1.0.1", 1746 | "bundled": true, 1747 | "requires": { 1748 | "jsonify": "0.0.0" 1749 | } 1750 | }, 1751 | "json-stringify-safe": { 1752 | "version": "5.0.1", 1753 | "bundled": true 1754 | }, 1755 | "json5": { 1756 | "version": "0.5.1", 1757 | "bundled": true 1758 | }, 1759 | "jsonfile": { 1760 | "version": "4.0.0", 1761 | "bundled": true, 1762 | "requires": { 1763 | "graceful-fs": "4.1.11" 1764 | } 1765 | }, 1766 | "jsonify": { 1767 | "version": "0.0.0", 1768 | "bundled": true 1769 | }, 1770 | "jsonpointer": { 1771 | "version": "4.0.1", 1772 | "bundled": true 1773 | }, 1774 | "jsprim": { 1775 | "version": "1.4.1", 1776 | "bundled": true, 1777 | "requires": { 1778 | "assert-plus": "1.0.0", 1779 | "extsprintf": "1.3.0", 1780 | "json-schema": "0.2.3", 1781 | "verror": "1.10.0" 1782 | } 1783 | }, 1784 | "kind-of": { 1785 | "version": "3.2.2", 1786 | "bundled": true, 1787 | "requires": { 1788 | "is-buffer": "1.1.5" 1789 | } 1790 | }, 1791 | "klaw": { 1792 | "version": "2.0.0", 1793 | "bundled": true, 1794 | "requires": { 1795 | "graceful-fs": "4.1.11" 1796 | } 1797 | }, 1798 | "lazy-cache": { 1799 | "version": "1.0.4", 1800 | "bundled": true, 1801 | "optional": true 1802 | }, 1803 | "lcid": { 1804 | "version": "1.0.0", 1805 | "bundled": true, 1806 | "requires": { 1807 | "invert-kv": "1.0.0" 1808 | } 1809 | }, 1810 | "lcov-parse": { 1811 | "version": "0.0.10", 1812 | "bundled": true 1813 | }, 1814 | "leven": { 1815 | "version": "2.1.0", 1816 | "bundled": true 1817 | }, 1818 | "levn": { 1819 | "version": "0.3.0", 1820 | "bundled": true, 1821 | "requires": { 1822 | "prelude-ls": "1.1.2", 1823 | "type-check": "0.3.2" 1824 | } 1825 | }, 1826 | "load-json-file": { 1827 | "version": "2.0.0", 1828 | "bundled": true, 1829 | "requires": { 1830 | "graceful-fs": "4.1.11", 1831 | "parse-json": "2.2.0", 1832 | "pify": "2.3.0", 1833 | "strip-bom": "3.0.0" 1834 | }, 1835 | "dependencies": { 1836 | "strip-bom": { 1837 | "version": "3.0.0", 1838 | "bundled": true 1839 | } 1840 | } 1841 | }, 1842 | "locate-path": { 1843 | "version": "2.0.0", 1844 | "bundled": true, 1845 | "requires": { 1846 | "p-locate": "2.0.0", 1847 | "path-exists": "3.0.0" 1848 | } 1849 | }, 1850 | "lodash": { 1851 | "version": "4.17.4", 1852 | "bundled": true 1853 | }, 1854 | "log-driver": { 1855 | "version": "1.2.5", 1856 | "bundled": true 1857 | }, 1858 | "longest": { 1859 | "version": "1.0.1", 1860 | "bundled": true 1861 | }, 1862 | "loose-envify": { 1863 | "version": "1.3.1", 1864 | "bundled": true, 1865 | "requires": { 1866 | "js-tokens": "3.0.2" 1867 | } 1868 | }, 1869 | "lru-cache": { 1870 | "version": "4.1.1", 1871 | "bundled": true, 1872 | "requires": { 1873 | "pseudomap": "1.0.2", 1874 | "yallist": "2.1.2" 1875 | } 1876 | }, 1877 | "makeerror": { 1878 | "version": "1.0.11", 1879 | "bundled": true, 1880 | "requires": { 1881 | "tmpl": "1.0.4" 1882 | } 1883 | }, 1884 | "marked": { 1885 | "version": "0.3.6", 1886 | "bundled": true 1887 | }, 1888 | "mem": { 1889 | "version": "1.1.0", 1890 | "bundled": true, 1891 | "requires": { 1892 | "mimic-fn": "1.1.0" 1893 | } 1894 | }, 1895 | "merge": { 1896 | "version": "1.2.0", 1897 | "bundled": true 1898 | }, 1899 | "micromatch": { 1900 | "version": "2.3.11", 1901 | "bundled": true, 1902 | "requires": { 1903 | "arr-diff": "2.0.0", 1904 | "array-unique": "0.2.1", 1905 | "braces": "1.8.5", 1906 | "expand-brackets": "0.1.5", 1907 | "extglob": "0.3.2", 1908 | "filename-regex": "2.0.1", 1909 | "is-extglob": "1.0.0", 1910 | "is-glob": "2.0.1", 1911 | "kind-of": "3.2.2", 1912 | "normalize-path": "2.1.1", 1913 | "object.omit": "2.0.1", 1914 | "parse-glob": "3.0.4", 1915 | "regex-cache": "0.4.4" 1916 | } 1917 | }, 1918 | "mime-db": { 1919 | "version": "1.30.0", 1920 | "bundled": true 1921 | }, 1922 | "mime-types": { 1923 | "version": "2.1.17", 1924 | "bundled": true, 1925 | "requires": { 1926 | "mime-db": "1.30.0" 1927 | } 1928 | }, 1929 | "mimic-fn": { 1930 | "version": "1.1.0", 1931 | "bundled": true 1932 | }, 1933 | "minami": { 1934 | "version": "1.1.1", 1935 | "bundled": true 1936 | }, 1937 | "minimatch": { 1938 | "version": "3.0.4", 1939 | "bundled": true, 1940 | "requires": { 1941 | "brace-expansion": "1.1.8" 1942 | } 1943 | }, 1944 | "minimist": { 1945 | "version": "1.2.0", 1946 | "bundled": true 1947 | }, 1948 | "mkdirp": { 1949 | "version": "0.5.1", 1950 | "bundled": true, 1951 | "requires": { 1952 | "minimist": "0.0.8" 1953 | }, 1954 | "dependencies": { 1955 | "minimist": { 1956 | "version": "0.0.8", 1957 | "bundled": true 1958 | } 1959 | } 1960 | }, 1961 | "ms": { 1962 | "version": "2.0.0", 1963 | "bundled": true 1964 | }, 1965 | "natural-compare": { 1966 | "version": "1.4.0", 1967 | "bundled": true 1968 | }, 1969 | "node-int64": { 1970 | "version": "0.4.0", 1971 | "bundled": true 1972 | }, 1973 | "node-notifier": { 1974 | "version": "5.1.2", 1975 | "bundled": true, 1976 | "requires": { 1977 | "growly": "1.3.0", 1978 | "semver": "5.4.1", 1979 | "shellwords": "0.1.1", 1980 | "which": "1.3.0" 1981 | } 1982 | }, 1983 | "normalize-package-data": { 1984 | "version": "2.4.0", 1985 | "bundled": true, 1986 | "requires": { 1987 | "hosted-git-info": "2.5.0", 1988 | "is-builtin-module": "1.0.0", 1989 | "semver": "5.4.1", 1990 | "validate-npm-package-license": "3.0.1" 1991 | } 1992 | }, 1993 | "normalize-path": { 1994 | "version": "2.1.1", 1995 | "bundled": true, 1996 | "requires": { 1997 | "remove-trailing-separator": "1.1.0" 1998 | } 1999 | }, 2000 | "npm-run-path": { 2001 | "version": "2.0.2", 2002 | "bundled": true, 2003 | "requires": { 2004 | "path-key": "2.0.1" 2005 | } 2006 | }, 2007 | "number-is-nan": { 2008 | "version": "1.0.1", 2009 | "bundled": true 2010 | }, 2011 | "nwmatcher": { 2012 | "version": "1.4.3", 2013 | "bundled": true 2014 | }, 2015 | "oauth-sign": { 2016 | "version": "0.8.2", 2017 | "bundled": true 2018 | }, 2019 | "object-assign": { 2020 | "version": "4.1.1", 2021 | "bundled": true 2022 | }, 2023 | "object.omit": { 2024 | "version": "2.0.1", 2025 | "bundled": true, 2026 | "requires": { 2027 | "for-own": "0.1.5", 2028 | "is-extendable": "0.1.1" 2029 | } 2030 | }, 2031 | "once": { 2032 | "version": "1.4.0", 2033 | "bundled": true, 2034 | "requires": { 2035 | "wrappy": "1.0.2" 2036 | } 2037 | }, 2038 | "optimist": { 2039 | "version": "0.6.1", 2040 | "bundled": true, 2041 | "requires": { 2042 | "minimist": "0.0.10", 2043 | "wordwrap": "0.0.3" 2044 | }, 2045 | "dependencies": { 2046 | "minimist": { 2047 | "version": "0.0.10", 2048 | "bundled": true 2049 | } 2050 | } 2051 | }, 2052 | "optionator": { 2053 | "version": "0.8.2", 2054 | "bundled": true, 2055 | "requires": { 2056 | "deep-is": "0.1.3", 2057 | "fast-levenshtein": "2.0.6", 2058 | "levn": "0.3.0", 2059 | "prelude-ls": "1.1.2", 2060 | "type-check": "0.3.2", 2061 | "wordwrap": "1.0.0" 2062 | }, 2063 | "dependencies": { 2064 | "wordwrap": { 2065 | "version": "1.0.0", 2066 | "bundled": true 2067 | } 2068 | } 2069 | }, 2070 | "os-homedir": { 2071 | "version": "1.0.2", 2072 | "bundled": true 2073 | }, 2074 | "os-locale": { 2075 | "version": "2.1.0", 2076 | "bundled": true, 2077 | "requires": { 2078 | "execa": "0.7.0", 2079 | "lcid": "1.0.0", 2080 | "mem": "1.1.0" 2081 | } 2082 | }, 2083 | "os-tmpdir": { 2084 | "version": "1.0.2", 2085 | "bundled": true 2086 | }, 2087 | "p-cancelable": { 2088 | "version": "0.3.0", 2089 | "bundled": true 2090 | }, 2091 | "p-finally": { 2092 | "version": "1.0.0", 2093 | "bundled": true 2094 | }, 2095 | "p-limit": { 2096 | "version": "1.1.0", 2097 | "bundled": true 2098 | }, 2099 | "p-locate": { 2100 | "version": "2.0.0", 2101 | "bundled": true, 2102 | "requires": { 2103 | "p-limit": "1.1.0" 2104 | } 2105 | }, 2106 | "parse-glob": { 2107 | "version": "3.0.4", 2108 | "bundled": true, 2109 | "requires": { 2110 | "glob-base": "0.3.0", 2111 | "is-dotfile": "1.0.3", 2112 | "is-extglob": "1.0.0", 2113 | "is-glob": "2.0.1" 2114 | } 2115 | }, 2116 | "parse-json": { 2117 | "version": "2.2.0", 2118 | "bundled": true, 2119 | "requires": { 2120 | "error-ex": "1.3.1" 2121 | } 2122 | }, 2123 | "parse5": { 2124 | "version": "1.5.1", 2125 | "bundled": true 2126 | }, 2127 | "path-exists": { 2128 | "version": "3.0.0", 2129 | "bundled": true 2130 | }, 2131 | "path-is-absolute": { 2132 | "version": "1.0.1", 2133 | "bundled": true 2134 | }, 2135 | "path-key": { 2136 | "version": "2.0.1", 2137 | "bundled": true 2138 | }, 2139 | "path-parse": { 2140 | "version": "1.0.5", 2141 | "bundled": true 2142 | }, 2143 | "path-type": { 2144 | "version": "2.0.0", 2145 | "bundled": true, 2146 | "requires": { 2147 | "pify": "2.3.0" 2148 | } 2149 | }, 2150 | "performance-now": { 2151 | "version": "2.1.0", 2152 | "bundled": true 2153 | }, 2154 | "pify": { 2155 | "version": "2.3.0", 2156 | "bundled": true 2157 | }, 2158 | "pinkie": { 2159 | "version": "2.0.4", 2160 | "bundled": true 2161 | }, 2162 | "pinkie-promise": { 2163 | "version": "2.0.1", 2164 | "bundled": true, 2165 | "requires": { 2166 | "pinkie": "2.0.4" 2167 | } 2168 | }, 2169 | "pkg-dir": { 2170 | "version": "2.0.0", 2171 | "bundled": true, 2172 | "requires": { 2173 | "find-up": "2.1.0" 2174 | } 2175 | }, 2176 | "prelude-ls": { 2177 | "version": "1.1.2", 2178 | "bundled": true 2179 | }, 2180 | "preserve": { 2181 | "version": "0.2.0", 2182 | "bundled": true 2183 | }, 2184 | "pretty-format": { 2185 | "version": "21.2.1", 2186 | "bundled": true, 2187 | "requires": { 2188 | "ansi-regex": "3.0.0", 2189 | "ansi-styles": "3.2.0" 2190 | }, 2191 | "dependencies": { 2192 | "ansi-regex": { 2193 | "version": "3.0.0", 2194 | "bundled": true 2195 | } 2196 | } 2197 | }, 2198 | "private": { 2199 | "version": "0.1.8", 2200 | "bundled": true 2201 | }, 2202 | "prr": { 2203 | "version": "0.0.0", 2204 | "bundled": true 2205 | }, 2206 | "pseudomap": { 2207 | "version": "1.0.2", 2208 | "bundled": true 2209 | }, 2210 | "punycode": { 2211 | "version": "1.4.1", 2212 | "bundled": true 2213 | }, 2214 | "qs": { 2215 | "version": "6.3.2", 2216 | "bundled": true 2217 | }, 2218 | "randomatic": { 2219 | "version": "1.1.7", 2220 | "bundled": true, 2221 | "requires": { 2222 | "is-number": "3.0.0", 2223 | "kind-of": "4.0.0" 2224 | }, 2225 | "dependencies": { 2226 | "is-number": { 2227 | "version": "3.0.0", 2228 | "bundled": true, 2229 | "requires": { 2230 | "kind-of": "3.2.2" 2231 | }, 2232 | "dependencies": { 2233 | "kind-of": { 2234 | "version": "3.2.2", 2235 | "bundled": true, 2236 | "requires": { 2237 | "is-buffer": "1.1.5" 2238 | } 2239 | } 2240 | } 2241 | }, 2242 | "kind-of": { 2243 | "version": "4.0.0", 2244 | "bundled": true, 2245 | "requires": { 2246 | "is-buffer": "1.1.5" 2247 | } 2248 | } 2249 | } 2250 | }, 2251 | "read-pkg": { 2252 | "version": "2.0.0", 2253 | "bundled": true, 2254 | "requires": { 2255 | "load-json-file": "2.0.0", 2256 | "normalize-package-data": "2.4.0", 2257 | "path-type": "2.0.0" 2258 | } 2259 | }, 2260 | "read-pkg-up": { 2261 | "version": "2.0.0", 2262 | "bundled": true, 2263 | "requires": { 2264 | "find-up": "2.1.0", 2265 | "read-pkg": "2.0.0" 2266 | } 2267 | }, 2268 | "regenerator-runtime": { 2269 | "version": "0.11.0", 2270 | "bundled": true 2271 | }, 2272 | "regex-cache": { 2273 | "version": "0.4.4", 2274 | "bundled": true, 2275 | "requires": { 2276 | "is-equal-shallow": "0.1.3" 2277 | } 2278 | }, 2279 | "remove-trailing-separator": { 2280 | "version": "1.1.0", 2281 | "bundled": true 2282 | }, 2283 | "repeat-element": { 2284 | "version": "1.1.2", 2285 | "bundled": true 2286 | }, 2287 | "repeat-string": { 2288 | "version": "1.6.1", 2289 | "bundled": true 2290 | }, 2291 | "repeating": { 2292 | "version": "2.0.1", 2293 | "bundled": true, 2294 | "requires": { 2295 | "is-finite": "1.0.2" 2296 | } 2297 | }, 2298 | "request": { 2299 | "version": "2.79.0", 2300 | "bundled": true, 2301 | "requires": { 2302 | "aws-sign2": "0.6.0", 2303 | "aws4": "1.6.0", 2304 | "caseless": "0.11.0", 2305 | "combined-stream": "1.0.5", 2306 | "extend": "3.0.1", 2307 | "forever-agent": "0.6.1", 2308 | "form-data": "2.1.4", 2309 | "har-validator": "2.0.6", 2310 | "hawk": "3.1.3", 2311 | "http-signature": "1.1.1", 2312 | "is-typedarray": "1.0.0", 2313 | "isstream": "0.1.2", 2314 | "json-stringify-safe": "5.0.1", 2315 | "mime-types": "2.1.17", 2316 | "oauth-sign": "0.8.2", 2317 | "qs": "6.3.2", 2318 | "stringstream": "0.0.5", 2319 | "tough-cookie": "2.3.3", 2320 | "tunnel-agent": "0.4.3", 2321 | "uuid": "3.1.0" 2322 | }, 2323 | "dependencies": { 2324 | "caseless": { 2325 | "version": "0.11.0", 2326 | "bundled": true 2327 | }, 2328 | "tunnel-agent": { 2329 | "version": "0.4.3", 2330 | "bundled": true 2331 | } 2332 | } 2333 | }, 2334 | "require-directory": { 2335 | "version": "2.1.1", 2336 | "bundled": true 2337 | }, 2338 | "require-main-filename": { 2339 | "version": "1.0.1", 2340 | "bundled": true 2341 | }, 2342 | "requizzle": { 2343 | "version": "0.2.1", 2344 | "bundled": true, 2345 | "requires": { 2346 | "underscore": "1.6.0" 2347 | } 2348 | }, 2349 | "resolve": { 2350 | "version": "1.1.7", 2351 | "bundled": true 2352 | }, 2353 | "right-align": { 2354 | "version": "0.1.3", 2355 | "bundled": true, 2356 | "optional": true, 2357 | "requires": { 2358 | "align-text": "0.1.4" 2359 | } 2360 | }, 2361 | "rimraf": { 2362 | "version": "2.6.2", 2363 | "bundled": true, 2364 | "requires": { 2365 | "glob": "7.1.2" 2366 | } 2367 | }, 2368 | "safe-buffer": { 2369 | "version": "5.1.1", 2370 | "bundled": true 2371 | }, 2372 | "sane": { 2373 | "version": "2.2.0", 2374 | "bundled": true, 2375 | "requires": { 2376 | "anymatch": "1.3.2", 2377 | "exec-sh": "0.2.1", 2378 | "fb-watchman": "2.0.0", 2379 | "minimatch": "3.0.4", 2380 | "minimist": "1.2.0", 2381 | "walker": "1.0.7", 2382 | "watch": "0.18.0" 2383 | } 2384 | }, 2385 | "sax": { 2386 | "version": "1.2.4", 2387 | "bundled": true 2388 | }, 2389 | "semver": { 2390 | "version": "5.4.1", 2391 | "bundled": true 2392 | }, 2393 | "set-blocking": { 2394 | "version": "2.0.0", 2395 | "bundled": true 2396 | }, 2397 | "shebang-command": { 2398 | "version": "1.2.0", 2399 | "bundled": true, 2400 | "requires": { 2401 | "shebang-regex": "1.0.0" 2402 | } 2403 | }, 2404 | "shebang-regex": { 2405 | "version": "1.0.0", 2406 | "bundled": true 2407 | }, 2408 | "shellwords": { 2409 | "version": "0.1.1", 2410 | "bundled": true 2411 | }, 2412 | "signal-exit": { 2413 | "version": "3.0.2", 2414 | "bundled": true 2415 | }, 2416 | "slash": { 2417 | "version": "1.0.0", 2418 | "bundled": true 2419 | }, 2420 | "sntp": { 2421 | "version": "1.0.9", 2422 | "bundled": true, 2423 | "requires": { 2424 | "hoek": "2.16.3" 2425 | }, 2426 | "dependencies": { 2427 | "hoek": { 2428 | "version": "2.16.3", 2429 | "bundled": true 2430 | } 2431 | } 2432 | }, 2433 | "source-map": { 2434 | "version": "0.5.7", 2435 | "bundled": true 2436 | }, 2437 | "source-map-support": { 2438 | "version": "0.5.0", 2439 | "bundled": true, 2440 | "requires": { 2441 | "source-map": "0.6.1" 2442 | }, 2443 | "dependencies": { 2444 | "source-map": { 2445 | "version": "0.6.1", 2446 | "bundled": true 2447 | } 2448 | } 2449 | }, 2450 | "spdx-correct": { 2451 | "version": "1.0.2", 2452 | "bundled": true, 2453 | "requires": { 2454 | "spdx-license-ids": "1.2.2" 2455 | } 2456 | }, 2457 | "spdx-expression-parse": { 2458 | "version": "1.0.4", 2459 | "bundled": true 2460 | }, 2461 | "spdx-license-ids": { 2462 | "version": "1.2.2", 2463 | "bundled": true 2464 | }, 2465 | "sprintf-js": { 2466 | "version": "1.0.3", 2467 | "bundled": true 2468 | }, 2469 | "sshpk": { 2470 | "version": "1.13.1", 2471 | "bundled": true, 2472 | "requires": { 2473 | "asn1": "0.2.3", 2474 | "assert-plus": "1.0.0", 2475 | "bcrypt-pbkdf": "1.0.1", 2476 | "dashdash": "1.14.1", 2477 | "ecc-jsbn": "0.1.1", 2478 | "getpass": "0.1.7", 2479 | "jsbn": "0.1.1", 2480 | "tweetnacl": "0.14.5" 2481 | } 2482 | }, 2483 | "string-length": { 2484 | "version": "2.0.0", 2485 | "bundled": true, 2486 | "requires": { 2487 | "astral-regex": "1.0.0", 2488 | "strip-ansi": "4.0.0" 2489 | }, 2490 | "dependencies": { 2491 | "ansi-regex": { 2492 | "version": "3.0.0", 2493 | "bundled": true 2494 | }, 2495 | "strip-ansi": { 2496 | "version": "4.0.0", 2497 | "bundled": true, 2498 | "requires": { 2499 | "ansi-regex": "3.0.0" 2500 | } 2501 | } 2502 | } 2503 | }, 2504 | "string-width": { 2505 | "version": "1.0.2", 2506 | "bundled": true, 2507 | "requires": { 2508 | "code-point-at": "1.1.0", 2509 | "is-fullwidth-code-point": "1.0.0", 2510 | "strip-ansi": "3.0.1" 2511 | } 2512 | }, 2513 | "stringstream": { 2514 | "version": "0.0.5", 2515 | "bundled": true 2516 | }, 2517 | "strip-ansi": { 2518 | "version": "3.0.1", 2519 | "bundled": true, 2520 | "requires": { 2521 | "ansi-regex": "2.1.1" 2522 | } 2523 | }, 2524 | "strip-bom": { 2525 | "version": "2.0.0", 2526 | "bundled": true, 2527 | "requires": { 2528 | "is-utf8": "0.2.1" 2529 | } 2530 | }, 2531 | "strip-eof": { 2532 | "version": "1.0.0", 2533 | "bundled": true 2534 | }, 2535 | "strip-json-comments": { 2536 | "version": "2.0.1", 2537 | "bundled": true 2538 | }, 2539 | "supports-color": { 2540 | "version": "4.5.0", 2541 | "bundled": true, 2542 | "requires": { 2543 | "has-flag": "2.0.0" 2544 | } 2545 | }, 2546 | "symbol-tree": { 2547 | "version": "3.2.2", 2548 | "bundled": true 2549 | }, 2550 | "taffydb": { 2551 | "version": "2.6.2", 2552 | "bundled": true 2553 | }, 2554 | "test-exclude": { 2555 | "version": "4.1.1", 2556 | "bundled": true, 2557 | "requires": { 2558 | "arrify": "1.0.1", 2559 | "micromatch": "2.3.11", 2560 | "object-assign": "4.1.1", 2561 | "read-pkg-up": "1.0.1", 2562 | "require-main-filename": "1.0.1" 2563 | }, 2564 | "dependencies": { 2565 | "find-up": { 2566 | "version": "1.1.2", 2567 | "bundled": true, 2568 | "requires": { 2569 | "path-exists": "2.1.0", 2570 | "pinkie-promise": "2.0.1" 2571 | } 2572 | }, 2573 | "load-json-file": { 2574 | "version": "1.1.0", 2575 | "bundled": true, 2576 | "requires": { 2577 | "graceful-fs": "4.1.11", 2578 | "parse-json": "2.2.0", 2579 | "pify": "2.3.0", 2580 | "pinkie-promise": "2.0.1", 2581 | "strip-bom": "2.0.0" 2582 | } 2583 | }, 2584 | "path-exists": { 2585 | "version": "2.1.0", 2586 | "bundled": true, 2587 | "requires": { 2588 | "pinkie-promise": "2.0.1" 2589 | } 2590 | }, 2591 | "path-type": { 2592 | "version": "1.1.0", 2593 | "bundled": true, 2594 | "requires": { 2595 | "graceful-fs": "4.1.11", 2596 | "pify": "2.3.0", 2597 | "pinkie-promise": "2.0.1" 2598 | } 2599 | }, 2600 | "read-pkg": { 2601 | "version": "1.1.0", 2602 | "bundled": true, 2603 | "requires": { 2604 | "load-json-file": "1.1.0", 2605 | "normalize-package-data": "2.4.0", 2606 | "path-type": "1.1.0" 2607 | } 2608 | }, 2609 | "read-pkg-up": { 2610 | "version": "1.0.1", 2611 | "bundled": true, 2612 | "requires": { 2613 | "find-up": "1.1.2", 2614 | "read-pkg": "1.1.0" 2615 | } 2616 | } 2617 | } 2618 | }, 2619 | "throat": { 2620 | "version": "4.1.0", 2621 | "bundled": true 2622 | }, 2623 | "tmpl": { 2624 | "version": "1.0.4", 2625 | "bundled": true 2626 | }, 2627 | "to-fast-properties": { 2628 | "version": "1.0.3", 2629 | "bundled": true 2630 | }, 2631 | "tough-cookie": { 2632 | "version": "2.3.3", 2633 | "bundled": true, 2634 | "requires": { 2635 | "punycode": "1.4.1" 2636 | } 2637 | }, 2638 | "tr46": { 2639 | "version": "0.0.3", 2640 | "bundled": true 2641 | }, 2642 | "trim-right": { 2643 | "version": "1.0.1", 2644 | "bundled": true 2645 | }, 2646 | "ts-jest": { 2647 | "version": "21.1.3", 2648 | "bundled": true, 2649 | "requires": { 2650 | "babel-core": "6.26.0", 2651 | "babel-plugin-istanbul": "4.1.5", 2652 | "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", 2653 | "babel-preset-jest": "21.2.0", 2654 | "fs-extra": "4.0.2", 2655 | "jest-config": "21.2.1", 2656 | "jest-util": "21.2.1", 2657 | "pkg-dir": "2.0.0", 2658 | "source-map-support": "0.5.0", 2659 | "yargs": "9.0.1" 2660 | } 2661 | }, 2662 | "tunnel-agent": { 2663 | "version": "0.6.0", 2664 | "bundled": true, 2665 | "requires": { 2666 | "safe-buffer": "5.1.1" 2667 | } 2668 | }, 2669 | "tweetnacl": { 2670 | "version": "0.14.5", 2671 | "bundled": true, 2672 | "optional": true 2673 | }, 2674 | "type-check": { 2675 | "version": "0.3.2", 2676 | "bundled": true, 2677 | "requires": { 2678 | "prelude-ls": "1.1.2" 2679 | } 2680 | }, 2681 | "typescript": { 2682 | "version": "2.5.3", 2683 | "bundled": true 2684 | }, 2685 | "uglify-js": { 2686 | "version": "2.8.29", 2687 | "bundled": true, 2688 | "optional": true, 2689 | "requires": { 2690 | "source-map": "0.5.7", 2691 | "uglify-to-browserify": "1.0.2", 2692 | "yargs": "3.10.0" 2693 | }, 2694 | "dependencies": { 2695 | "camelcase": { 2696 | "version": "1.2.1", 2697 | "bundled": true, 2698 | "optional": true 2699 | }, 2700 | "cliui": { 2701 | "version": "2.1.0", 2702 | "bundled": true, 2703 | "optional": true, 2704 | "requires": { 2705 | "center-align": "0.1.3", 2706 | "right-align": "0.1.3", 2707 | "wordwrap": "0.0.2" 2708 | } 2709 | }, 2710 | "wordwrap": { 2711 | "version": "0.0.2", 2712 | "bundled": true, 2713 | "optional": true 2714 | }, 2715 | "yargs": { 2716 | "version": "3.10.0", 2717 | "bundled": true, 2718 | "optional": true, 2719 | "requires": { 2720 | "camelcase": "1.2.1", 2721 | "cliui": "2.1.0", 2722 | "decamelize": "1.2.0", 2723 | "window-size": "0.1.0" 2724 | } 2725 | } 2726 | } 2727 | }, 2728 | "uglify-to-browserify": { 2729 | "version": "1.0.2", 2730 | "bundled": true, 2731 | "optional": true 2732 | }, 2733 | "underscore": { 2734 | "version": "1.6.0", 2735 | "bundled": true 2736 | }, 2737 | "underscore-contrib": { 2738 | "version": "0.3.0", 2739 | "bundled": true, 2740 | "requires": { 2741 | "underscore": "1.6.0" 2742 | } 2743 | }, 2744 | "universalify": { 2745 | "version": "0.1.1", 2746 | "bundled": true 2747 | }, 2748 | "uuid": { 2749 | "version": "3.1.0", 2750 | "bundled": true 2751 | }, 2752 | "validate-npm-package-license": { 2753 | "version": "3.0.1", 2754 | "bundled": true, 2755 | "requires": { 2756 | "spdx-correct": "1.0.2", 2757 | "spdx-expression-parse": "1.0.4" 2758 | } 2759 | }, 2760 | "verror": { 2761 | "version": "1.10.0", 2762 | "bundled": true, 2763 | "requires": { 2764 | "assert-plus": "1.0.0", 2765 | "core-util-is": "1.0.2", 2766 | "extsprintf": "1.3.0" 2767 | } 2768 | }, 2769 | "walker": { 2770 | "version": "1.0.7", 2771 | "bundled": true, 2772 | "requires": { 2773 | "makeerror": "1.0.11" 2774 | } 2775 | }, 2776 | "watch": { 2777 | "version": "0.18.0", 2778 | "bundled": true, 2779 | "requires": { 2780 | "exec-sh": "0.2.1", 2781 | "minimist": "1.2.0" 2782 | } 2783 | }, 2784 | "webidl-conversions": { 2785 | "version": "4.0.2", 2786 | "bundled": true 2787 | }, 2788 | "whatwg-encoding": { 2789 | "version": "1.0.2", 2790 | "bundled": true, 2791 | "requires": { 2792 | "iconv-lite": "0.4.13" 2793 | } 2794 | }, 2795 | "whatwg-url": { 2796 | "version": "4.8.0", 2797 | "bundled": true, 2798 | "requires": { 2799 | "tr46": "0.0.3", 2800 | "webidl-conversions": "3.0.1" 2801 | }, 2802 | "dependencies": { 2803 | "webidl-conversions": { 2804 | "version": "3.0.1", 2805 | "bundled": true 2806 | } 2807 | } 2808 | }, 2809 | "which": { 2810 | "version": "1.3.0", 2811 | "bundled": true, 2812 | "requires": { 2813 | "isexe": "2.0.0" 2814 | } 2815 | }, 2816 | "which-module": { 2817 | "version": "2.0.0", 2818 | "bundled": true 2819 | }, 2820 | "window-size": { 2821 | "version": "0.1.0", 2822 | "bundled": true, 2823 | "optional": true 2824 | }, 2825 | "wordwrap": { 2826 | "version": "0.0.3", 2827 | "bundled": true 2828 | }, 2829 | "worker-farm": { 2830 | "version": "1.5.0", 2831 | "bundled": true, 2832 | "requires": { 2833 | "errno": "0.1.4", 2834 | "xtend": "4.0.1" 2835 | } 2836 | }, 2837 | "wrap-ansi": { 2838 | "version": "2.1.0", 2839 | "bundled": true, 2840 | "requires": { 2841 | "string-width": "1.0.2", 2842 | "strip-ansi": "3.0.1" 2843 | } 2844 | }, 2845 | "wrappy": { 2846 | "version": "1.0.2", 2847 | "bundled": true 2848 | }, 2849 | "write-file-atomic": { 2850 | "version": "2.3.0", 2851 | "bundled": true, 2852 | "requires": { 2853 | "graceful-fs": "4.1.11", 2854 | "imurmurhash": "0.1.4", 2855 | "signal-exit": "3.0.2" 2856 | } 2857 | }, 2858 | "xml-name-validator": { 2859 | "version": "2.0.1", 2860 | "bundled": true 2861 | }, 2862 | "xmlcreate": { 2863 | "version": "1.0.2", 2864 | "bundled": true 2865 | }, 2866 | "xtend": { 2867 | "version": "4.0.1", 2868 | "bundled": true 2869 | }, 2870 | "y18n": { 2871 | "version": "3.2.1", 2872 | "bundled": true 2873 | }, 2874 | "yallist": { 2875 | "version": "2.1.2", 2876 | "bundled": true 2877 | }, 2878 | "yargs": { 2879 | "version": "9.0.1", 2880 | "bundled": true, 2881 | "requires": { 2882 | "camelcase": "4.1.0", 2883 | "cliui": "3.2.0", 2884 | "decamelize": "1.2.0", 2885 | "get-caller-file": "1.0.2", 2886 | "os-locale": "2.1.0", 2887 | "read-pkg-up": "2.0.0", 2888 | "require-directory": "2.1.1", 2889 | "require-main-filename": "1.0.1", 2890 | "set-blocking": "2.0.0", 2891 | "string-width": "2.1.1", 2892 | "which-module": "2.0.0", 2893 | "y18n": "3.2.1", 2894 | "yargs-parser": "7.0.0" 2895 | }, 2896 | "dependencies": { 2897 | "ansi-regex": { 2898 | "version": "3.0.0", 2899 | "bundled": true 2900 | }, 2901 | "is-fullwidth-code-point": { 2902 | "version": "2.0.0", 2903 | "bundled": true 2904 | }, 2905 | "string-width": { 2906 | "version": "2.1.1", 2907 | "bundled": true, 2908 | "requires": { 2909 | "is-fullwidth-code-point": "2.0.0", 2910 | "strip-ansi": "4.0.0" 2911 | } 2912 | }, 2913 | "strip-ansi": { 2914 | "version": "4.0.0", 2915 | "bundled": true, 2916 | "requires": { 2917 | "ansi-regex": "3.0.0" 2918 | } 2919 | } 2920 | } 2921 | }, 2922 | "yargs-parser": { 2923 | "version": "7.0.0", 2924 | "bundled": true, 2925 | "requires": { 2926 | "camelcase": "4.1.0" 2927 | } 2928 | } 2929 | } 2930 | }, 2931 | "core-js": { 2932 | "version": "2.5.1", 2933 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", 2934 | "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" 2935 | }, 2936 | "encoding": { 2937 | "version": "0.1.12", 2938 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 2939 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", 2940 | "requires": { 2941 | "iconv-lite": "0.4.19" 2942 | } 2943 | }, 2944 | "iconv-lite": { 2945 | "version": "0.4.19", 2946 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 2947 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 2948 | }, 2949 | "is-stream": { 2950 | "version": "1.1.0", 2951 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 2952 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 2953 | }, 2954 | "node-fetch": { 2955 | "version": "1.7.3", 2956 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", 2957 | "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", 2958 | "requires": { 2959 | "encoding": "0.1.12", 2960 | "is-stream": "1.1.0" 2961 | } 2962 | }, 2963 | "regenerator-runtime": { 2964 | "version": "0.10.5", 2965 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", 2966 | "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" 2967 | }, 2968 | "typescript": { 2969 | "version": "2.5.3", 2970 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.3.tgz", 2971 | "integrity": "sha512-ptLSQs2S4QuS6/OD1eAKG+S5G8QQtrU5RT32JULdZQtM1L3WTi34Wsu48Yndzi8xsObRAB9RPt/KhA9wlpEF6w==", 2972 | "dev": true 2973 | } 2974 | } 2975 | } 2976 | --------------------------------------------------------------------------------