diff --git a/.gitignore b/.gitignore index 69caa028..5d31208f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ node_modules/* .idea/* dist -docs +bundle.js +bundle.js.map +stats.json +lib +docs/code/* +docs/js/planner* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..94fa2e2d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +language: node_js +node_js: + - "node" +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.9 +install: + - CC=gcc-4.9 CXX=g++-4.9 npm install +script: + - npm test + - npm run doc +cache: + npm: true + apt: true + directories: + - node_modules +deploy: + - provider: pages + skip-cleanup: true + github-token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable + keep-history: true + local-dir: docs + on: + tags: false + branch: dev + node_js: "node" diff --git a/README.md b/README.md index d37c9cbc..2a98f708 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,46 @@ -# 🛸 Planner.js +# Planner.js: A JS library for route planning -The JavaScript library for journey planning. +🛸 [![Build Status](https://travis-ci.org/openplannerteam/planner.js.svg?branch=dev)](https://travis-ci.org/openplannerteam/planner.js) 🚴‍♂️ [![MIT License](https://img.shields.io/github/license/openplannerteam/planner.js.svg?maxAge=2592000)](https://github.com/openplannerteam/planner.js/blob/master/LICENSE) 🚉 -CDN versions: _coming in February_ +Current status: _to be launched in February_ 🚀 -For now: clone the repository, run `npm install` and use your [typescript compiler](https://www.typescriptlang.org/) (`tsc`) to create the files. +For now: clone the repository, run `npm install` and `npm build`. Afterwards you can use it as follows: -Next, use it as follows: +Include it in the browser: +```html + +``` -_TODO_ +Include it in your JavaScript project: +```javascript +// Not yet published on NPM... +const Planner = require('plannerjs').default; +``` +Use it in both environments: +```javascript +const planner = new Planner(); +planner.query({ + publicTransportOnly: true, + from: "http://irail.be/stations/NMBS/008812005", // Brussels North + to: "http://irail.be/stations/NMBS/008892007", // Ghent-Sint-Pieters + minimumDepartureTime: new Date(), + maximumTransferDuration: 30 * 60 * 1000, // 30 minutes +}).then((publicTransportResult) => { + publicTransportResult.take(15).on('data', (path) => { + console.log(path); + }); +}).catch((reason) => { + console.error(reason); +}); +``` +## Documentation + +For further instructions, follow the documentation at https://openplannerteam.github.io/planner.js/ + +## Developing + + * Building the docs with typedoc: `npm run doc` + * Testing with jest: `npm test` + * Create a new browser version with `npm run browser` diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..6ee16ea2 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +## Documentation + +This folder is used for the documentation website at https://openplannerteam.github.io/planner.js/ + +Travis-CI will automatically add a folder code/ in here with the TypeDoc documentation extracted from the codebase. Do not change the gh-pages branch manually. Instead, change the contents of docs/ in the master branch, or change the documentation in the codebase itself to change the code documentation. \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..8ff8f211 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,185 @@ + + + Doc Planner.js – The ultimate JavaScript route planning framework + + + + + + + +
+
+
+

Planner.js

+

The ultimate JavaScript framework for journey planning

+

Your next steps: +

+

+
+

Demo

+

+ See the Pen Using the new JavaScript route + planner on CodePen. +

+
+ +
+

Architecture

+

+ Planner.js makes heavy use of inversify, a dependency injection + framework. + This allows anyone to make a quick custom build of a route planner, with specific needs. + Configuration of what classes should be injected where, happens by inside an inversify Container. + The default Container (used by the CDN version) can be found + in inversify.config.ts +

+

Different Interfaces

+

+ For a full overview, please consult our code documentation. + The interfaces for the Planner are split in: +

+

Providers

+

+ Providers serve as data interfaces for all fetchers of the same type (registered in the inversify + Container). + When a class needs some data, it injects a Provider of the right type. + The Provider determines the right fetcher and passes any data requests through to that fetcher. +

+

+ Right now, there are two types of data, so there are two types of providers: + connections providers and + stops providers +

+

Fetchers

+

+ These are ways to fetch data from different sources. Each fetcher corresponds to one source. + We will use the Comunica framework to fetch the data as an intelligent agent. + For now, we are just using the Linked Data Fetch NPM package and manually implement the routable + tiles and Linked Connections specification. +

+

+ Right now, there are two types of data, so there are two types of fetchers: + connections fetchers and + stops fetchers +

+

Planners

+

These represent the core algorithms of this library. There are + road planners and + public-transport planners. + Additionally, there are + reachable stops finders, + which are used in certain steps of public-transport planner algorithms +

+ +

Creating your own Planner version

+

+ We still need to properly write this part of the documentation. + However, the code may help you out understanding how it currently works. + By default, the file inversify.config.ts is going to be used to build the Planner. + The Planner instance must be instantiated with the dependencies container. + If you bundle a different dependencies container with your Planner, + your specific Planner will be able to act differently. +

+

Phases

+

+ To allow maximum flexibility, some algorithms allow injecting multiple implementations of the same interface, + depending on the phase of the algorithm. For example: +

+
container.bind<IJourneyExtractor>(TYPES.JourneyExtractor).to(JourneyExtractorDefault);
+container.bind<IRoadPlanner>(TYPES.RoadPlanner).to(RoadPlannerBirdsEye).whenTargetTagged("phase", JourneyExtractionPhase.Initial);
+container.bind<IRoadPlanner>(TYPES.RoadPlanner).to(RoadPlannerBirdsEye).whenTargetTagged("phase", JourneyExtractionPhase.Transfer);
+container.bind<IRoadPlanner>(TYPES.RoadPlanner).to(RoadPlannerBirdsEye).whenTargetTagged("phase", JourneyExtractionPhase.Final);
+

+ This example is pointless right now, because only one road planner is implemented +

+

Catalog

+

+ Each container should have a Catalog which holds the access URLs (and other meta data) of all data sources. + For example, a planner that should only plan NMBS routes could have this catalog: +

+
const catalog = new Catalog();
+catalog.addStopsFetcher("http://irail.be/stations/NMBS/", "https://irail.be/stations/NMBS");
+catalog.addConnectionsFetcher("https://graph.irail.be/sncb/connections", TravelMode.Train);
+
+container.bind<Catalog>(TYPES.Catalog).toConstantValue(catalog);
+

+

Factories

+

+ Providers create all the necessary fetchers based on the data sources configured in the catalog. + Factories form the glue between all these parts: they create a fetcher based on a catalog entry on + behalf of a provider. Warning: subject to change +

+

+ For example: +

+
container.bind<IConnectionsProvider>(TYPES.ConnectionsProvider).to(ConnectionsProviderPassthrough).inSingletonScope();
+container.bind<IConnectionsFetcher>(TYPES.ConnectionsFetcher).to(ConnectionsFetcherLazy);
+container.bind<interfaces.Factory<IConnectionsFetcher>>(TYPES.ConnectionsFetcherFactory)
+  .toFactory<IConnectionsFetcher>(
+    (context: interfaces.Context) =>
+      (accessUrl: string, travelMode: TravelMode) => {
+        const fetcher = context.container.get<ConnectionsFetcherLazy>(TYPES.ConnectionsFetcher);
+
+        fetcher.setAccessUrl(accessUrl);
+        fetcher.setTravelMode(travelMode);
+
+        return fetcher;
+      },
+  );
+

+

Possibilities

+

+ One could make a dependency container specifically for shared bikes and public transport. +

+

+ Another example would be to create a dependency container for public transport systems only. + In this case, we would change the RoadPlanner to just using RoadPlannerBirdsEye, in order to + understand where we can transfer. +

+
+
+
+
+ + + diff --git a/docs/js/.gitkeep b/docs/js/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..74292c86 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8743 @@ +{ + "name": "plannerjs", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } + } + }, + "@rdfjs/data-model": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rdfjs/data-model/-/data-model-1.1.0.tgz", + "integrity": "sha512-vK7TlSFBJQihqMoMgXK/VtcRV+rCQSOLB9VGAfv4Pr6BzUbBcR0CeM/RpkD4bHGX3816eaaURH1CNgN7togWdw==" + }, + "@types/asynciterator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/asynciterator/-/asynciterator-1.1.1.tgz", + "integrity": "sha512-KgjXxTtWbMW7UA4oZauIfg2rCl5+5LbsoVF5DwwpXVQxzSbez2PQ9NAlbJlBjIHqKLOpWcdjqL+wyrNepvTZOg==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/node": "*" + } + }, + "@types/events": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", + "dev": true + }, + "@types/fs-extra": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "integrity": "sha512-DsknoBvD8s+RFfSGjmERJ7ZOP1HI0UZRA3FSI+Zakhrc/Gy26YQsLI+m5V5DHxroHRJqCDLKJp7Hixn8zyaF7g==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/handlebars": { + "version": "4.0.39", + "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.39.tgz", + "integrity": "sha512-vjaS7Q0dVqFp85QhyPSZqDKnTTCemcSHNHFvDdalO1s0Ifz5KuE64jQD5xoUkfdWwF4WpqdJEl7LsWH8rzhKJA==", + "dev": true + }, + "@types/haversine": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/haversine/-/haversine-1.1.0.tgz", + "integrity": "sha512-r3czDJZMjF/BpTzpzmehmAml68GMusKuD7es8qjl5kNtrfQAZ8PyARUUZudHq+qEk3VEln1WzSJ8KMQsxQQbPQ==", + "dev": true + }, + "@types/highlight.js": { + "version": "9.12.3", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", + "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", + "dev": true + }, + "@types/jest": { + "version": "23.3.7", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.7.tgz", + "integrity": "sha512-N0p6mHrS0RHC3A9hHN4QH1RM2fGSb2E8rt6ONEK5xKSnyKtn/JAhr1VritkCn6cdyDBephVB80THqJGWzK8FAw==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.118", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.118.tgz", + "integrity": "sha512-iiJbKLZbhSa6FYRip/9ZDX6HXhayXLDGY2Fqws9cOkEQ6XeKfaxB0sC541mowZJueYyMnVUmmG+al5/4fCDrgw==", + "dev": true + }, + "@types/marked": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.2.tgz", + "integrity": "sha512-cDB930/7MbzaGF6U3IwSQp6XBru8xWajF5PV2YZZeV8DyiliTuld11afVztGI9+yJZ29il5E+NpGA6ooV/Cjkg==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", + "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==", + "dev": true + }, + "@types/rdf-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/rdf-js/-/rdf-js-1.0.1.tgz", + "integrity": "sha512-2uN1k9sRdV3oOvt8hHlzkJyb74JbqAHFPe8lrbYXXj5Y3JCHtzDAZyYc2x/Tyw4VWBL+mg0dEgb0VCIJiGAYFA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/shelljs": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.0.tgz", + "integrity": "sha512-vs1hCC8RxLHRu2bwumNyYRNrU3o8BtZhLysH5A4I98iYmA2APl6R3uNQb5ihl+WiwH0xdC9LLO+vRrXLs/Kyxg==", + "dev": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "@webassemblyjs/ast": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", + "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", + "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", + "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", + "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", + "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", + "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", + "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", + "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", + "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", + "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", + "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/utf8": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", + "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", + "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/helper-wasm-section": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-opt": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", + "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", + "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", + "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", + "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/floating-point-hex-parser": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-code-frame": "1.7.11", + "@webassemblyjs/helper-fsm": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", + "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "dev": true + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "dev": true, + "requires": { + "acorn": "^5.0.0" + } + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz", + "integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg==" + } + } + }, + "acorn-walk": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.0.tgz", + "integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg==" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynciterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/asynciterator/-/asynciterator-2.0.1.tgz", + "integrity": "sha512-aVLheZsDNU5qpOv6jZEHnFv79GfEi+N0w/OLmMmXZfGD8XFFmPsRhkSqleNl9jS6mqy/DNoV7tXGcI0S3cUvHQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + } + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", + "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", + "dev": true, + "requires": { + "babel-plugin-istanbul": "^4.1.6", + "babel-preset-jest": "^23.2.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-istanbul": { + "version": "4.1.6", + "resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", + "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.13.0", + "find-up": "^2.1.0", + "istanbul-lib-instrument": "^1.10.1", + "test-exclude": "^4.2.1" + } + }, + "babel-plugin-jest-hoist": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", + "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-preset-jest": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", + "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^23.2.0", + "babel-plugin-syntax-object-rest-spread": "^6.13.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.x.x" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "bs-logger": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.5.tgz", + "integrity": "sha512-uFLE0LFMxrH8Z5Hd9QgivvRbrl/NFkOTHzGhlqQxsnmx5JBLrp4bc249afLL+GccyY/8hkcGi2LpVaOzaEY0nQ==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "^2.0.0" + } + }, + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cacache": { + "version": "10.0.4", + "resolved": "http://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "capture-exit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", + "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", + "dev": true, + "requires": { + "rsvp": "^3.3.3" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + }, + "dependencies": { + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "cssom": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", + "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==" + }, + "cssstyle": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", + "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "requires": { + "cssom": "0.3.x" + } + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz", + "integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==", + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "^2.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "duplexify": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + } + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "events": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", + "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", + "dev": true, + "requires": { + "merge": "^1.2.0" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "expect": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-23.6.0.tgz", + "integrity": "sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "jest-diff": "^23.6.0", + "jest-get-type": "^22.1.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "follow-redirects": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", + "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", + "requires": { + "debug": "=3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "global-modules-path": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz", + "integrity": "sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==", + "dev": true + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "handlebars": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "dev": true, + "requires": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "haversine": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/haversine/-/haversine-1.1.0.tgz", + "integrity": "sha1-CyOAy22cEOnxIk/CtRPMYQGNX/c=" + }, + "highlight.js": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz", + "integrity": "sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, + "requires": { + "pkg-dir": "^2.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "inversify": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.0.1.tgz", + "integrity": "sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-generator-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", + "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + }, + "dependencies": { + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-api": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", + "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", + "dev": true, + "requires": { + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-23.6.0.tgz", + "integrity": "sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==", + "dev": true, + "requires": { + "import-local": "^1.0.0", + "jest-cli": "^23.6.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "jest-cli": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.6.0.tgz", + "integrity": "sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "import-local": "^1.0.0", + "is-ci": "^1.0.10", + "istanbul-api": "^1.3.1", + "istanbul-lib-coverage": "^1.2.0", + "istanbul-lib-instrument": "^1.10.1", + "istanbul-lib-source-maps": "^1.2.4", + "jest-changed-files": "^23.4.2", + "jest-config": "^23.6.0", + "jest-environment-jsdom": "^23.4.0", + "jest-get-type": "^22.1.0", + "jest-haste-map": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0", + "jest-resolve-dependencies": "^23.6.0", + "jest-runner": "^23.6.0", + "jest-runtime": "^23.6.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "jest-watcher": "^23.4.0", + "jest-worker": "^23.2.0", + "micromatch": "^2.3.11", + "node-notifier": "^5.2.1", + "prompts": "^0.1.9", + "realpath-native": "^1.0.0", + "rimraf": "^2.5.4", + "slash": "^1.0.0", + "string-length": "^2.0.0", + "strip-ansi": "^4.0.0", + "which": "^1.2.12", + "yargs": "^11.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "jest-changed-files": { + "version": "23.4.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz", + "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==", + "dev": true, + "requires": { + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.6.0.tgz", + "integrity": "sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==", + "dev": true, + "requires": { + "babel-core": "^6.0.0", + "babel-jest": "^23.6.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^23.4.0", + "jest-environment-node": "^23.4.0", + "jest-get-type": "^22.1.0", + "jest-jasmine2": "^23.6.0", + "jest-regex-util": "^23.3.0", + "jest-resolve": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "micromatch": "^2.3.11", + "pretty-format": "^23.6.0" + } + }, + "jest-diff": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.6.0.tgz", + "integrity": "sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff": "^3.2.0", + "jest-get-type": "^22.1.0", + "pretty-format": "^23.6.0" + } + }, + "jest-docblock": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz", + "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz", + "integrity": "sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "pretty-format": "^23.6.0" + } + }, + "jest-environment-jsdom": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz", + "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=", + "dev": true, + "requires": { + "jest-mock": "^23.2.0", + "jest-util": "^23.4.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz", + "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=", + "dev": true, + "requires": { + "jest-mock": "^23.2.0", + "jest-util": "^23.4.0" + } + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "http://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-haste-map": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.6.0.tgz", + "integrity": "sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==", + "dev": true, + "requires": { + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.1.11", + "invariant": "^2.2.4", + "jest-docblock": "^23.2.0", + "jest-serializer": "^23.0.1", + "jest-worker": "^23.2.0", + "micromatch": "^2.3.11", + "sane": "^2.0.0" + } + }, + "jest-jasmine2": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz", + "integrity": "sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==", + "dev": true, + "requires": { + "babel-traverse": "^6.0.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^23.6.0", + "is-generator-fn": "^1.0.0", + "jest-diff": "^23.6.0", + "jest-each": "^23.6.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "pretty-format": "^23.6.0" + } + }, + "jest-leak-detector": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz", + "integrity": "sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==", + "dev": true, + "requires": { + "pretty-format": "^23.6.0" + } + }, + "jest-matcher-utils": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz", + "integrity": "sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.1.0", + "pretty-format": "^23.6.0" + } + }, + "jest-message-util": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz", + "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0-beta.35", + "chalk": "^2.0.1", + "micromatch": "^2.3.11", + "slash": "^1.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz", + "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=", + "dev": true + }, + "jest-regex-util": { + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", + "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", + "dev": true + }, + "jest-resolve": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.6.0.tgz", + "integrity": "sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==", + "dev": true, + "requires": { + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "realpath-native": "^1.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz", + "integrity": "sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==", + "dev": true, + "requires": { + "jest-regex-util": "^23.3.0", + "jest-snapshot": "^23.6.0" + } + }, + "jest-runner": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.6.0.tgz", + "integrity": "sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==", + "dev": true, + "requires": { + "exit": "^0.1.2", + "graceful-fs": "^4.1.11", + "jest-config": "^23.6.0", + "jest-docblock": "^23.2.0", + "jest-haste-map": "^23.6.0", + "jest-jasmine2": "^23.6.0", + "jest-leak-detector": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-runtime": "^23.6.0", + "jest-util": "^23.4.0", + "jest-worker": "^23.2.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + }, + "dependencies": { + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "jest-runtime": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.6.0.tgz", + "integrity": "sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==", + "dev": true, + "requires": { + "babel-core": "^6.0.0", + "babel-plugin-istanbul": "^4.1.6", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "exit": "^0.1.2", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.11", + "jest-config": "^23.6.0", + "jest-haste-map": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0", + "jest-resolve": "^23.6.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "micromatch": "^2.3.11", + "realpath-native": "^1.0.0", + "slash": "^1.0.0", + "strip-bom": "3.0.0", + "write-file-atomic": "^2.1.0", + "yargs": "^11.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "jest-serializer": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz", + "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=", + "dev": true + }, + "jest-snapshot": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.6.0.tgz", + "integrity": "sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==", + "dev": true, + "requires": { + "babel-types": "^6.0.0", + "chalk": "^2.0.1", + "jest-diff": "^23.6.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-resolve": "^23.6.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^23.6.0", + "semver": "^5.5.0" + } + }, + "jest-util": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz", + "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=", + "dev": true, + "requires": { + "callsites": "^2.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.11", + "is-ci": "^1.0.10", + "jest-message-util": "^23.4.0", + "mkdirp": "^0.5.1", + "slash": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "jest-validate": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", + "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.1.0", + "leven": "^2.1.0", + "pretty-format": "^23.6.0" + } + }, + "jest-watcher": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz", + "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", + "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", + "dev": true, + "requires": { + "merge-stream": "^1.0.1" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonld": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-1.1.0.tgz", + "integrity": "sha512-tx87xNtu2hGabr7mhSyXTI8q+Fz3pl+50B/JislFPwAz8ud0KTTQpNjU74tJIegFAHve9UFYzzj4YVTIrac0Hw==", + "requires": { + "rdf-canonize": "^0.2.1", + "request": "^2.83.0", + "semver": "^5.5.0", + "xmldom": "0.1.19" + }, + "dependencies": { + "xmldom": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.19.tgz", + "integrity": "sha1-Yx/Ad3bv2EEYvyUXGzftTQdaCrw=" + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "kleur": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz", + "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "ldfetch": { + "version": "1.1.1-alpha", + "resolved": "https://registry.npmjs.org/ldfetch/-/ldfetch-1.1.1-alpha.tgz", + "integrity": "sha512-9Mao1ltrI/EItYwZEq4W70aBYZ7iLHU+yYgpzSFTYTHGssxNRN8vZNJ/1nf9DHTGwcWmEEyfYeKsEU/SvHoxHg==", + "requires": { + "@rdfjs/data-model": "^1.1.0", + "commander": "^2.17.1", + "follow-redirects": "^1.5.5", + "http-cache-semantics": "^3.7.3", + "jsdom": "^11.12.0", + "jsonld": "^1.0.2", + "n3": "1.0.0-alpha", + "node-cache": "^4.2.0", + "q": "^1.5.1", + "rdfa-processor": "^0.0.5", + "rdfxmlprocessor": "0.0.3-alpha", + "wreck": "^12.5.1", + "xmldom": "^0.1.27" + }, + "dependencies": { + "n3": { + "version": "1.0.0-alpha", + "resolved": "https://registry.npmjs.org/n3/-/n3-1.0.0-alpha.tgz", + "integrity": "sha512-JJCef2qbYZCkwWkH6GitR/QwJrQ0VMoeAM1EdTl+xx7m6OLRUI1zUh1afBMRjslIWdkZodROf8gudY2vhXmByA==" + } + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "loader-runner": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", + "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "marked": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.4.0.tgz", + "integrity": "sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw==", + "dev": true + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "n3": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/n3/-/n3-0.11.2.tgz", + "integrity": "sha512-ICSiOmFLbZ4gI35+4H3e2vYGHDC944WZkCa1iVNRAx/mRZESEevQNFhfHaui/lhqynoZYvBVDNjM/2Tfd3TICQ==" + }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-cache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-4.2.0.tgz", + "integrity": "sha512-obRu6/f7S024ysheAjoYFEEBqqDWv4LOMNJEuO8vMeEw2AT4z+NCzO4hlc2lhI4vATzbCQv6kke9FVdx0RbCOw==", + "requires": { + "clone": "2.x", + "lodash": "4.x" + } + }, + "node-forge": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", + "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-notifier": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.3.0.tgz", + "integrity": "sha512-AhENzCSGZnZJgBARsUjnQ7DnZbzyP+HxlVXuD0xqAnvL8q+OqtSX7lGg9e8nHzwXkMMXNdVeqq4E2M3EUAqX6Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nwsapi": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", + "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-shim": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", + "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pre-commit": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz", + "integrity": "sha1-287g7p3nI15X95xW186UZBpp7sY=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "spawn-sync": "^1.0.15", + "which": "1.2.x" + }, + "dependencies": { + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "prettier": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.3.tgz", + "integrity": "sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==", + "dev": true + }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", + "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prompts": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", + "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==", + "dev": true, + "requires": { + "kleur": "^2.0.1", + "sisteransi": "^0.1.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "rdf-canonize": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-0.2.4.tgz", + "integrity": "sha512-xwAEHJt8FTe4hP9CjFgwQPFdszu4iwEintk31+9eh0rljC28vm9EhoaIlC1rQx5LaCB5oHom4+yoei4+DTdRjQ==", + "requires": { + "bindings": "^1.3.0", + "nan": "^2.10.0", + "node-forge": "^0.7.1", + "semver": "^5.4.1" + } + }, + "rdfa-processor": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/rdfa-processor/-/rdfa-processor-0.0.5.tgz", + "integrity": "sha512-272KPQ5xrBmTh4DijaBSoS0A1fXMzhqmctbvOl7Ud0R1X+km1aR/CZ3pD7Lbjiko30tNY1CTseysnCvZkW2jLg==", + "requires": { + "n3": "^1.0.0-alpha" + }, + "dependencies": { + "n3": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/n3/-/n3-1.0.0-beta.2.tgz", + "integrity": "sha512-dY0Q21JhNJozPMSijKI9phfgocXb7hF9F8zOPnsRu0Dy61eQwQVKcFEw59V0sn2F/neJjNg7WHmNtGLMkPpKPA==" + } + } + }, + "rdfxmlprocessor": { + "version": "0.0.3-alpha", + "resolved": "https://registry.npmjs.org/rdfxmlprocessor/-/rdfxmlprocessor-0.0.3-alpha.tgz", + "integrity": "sha512-QrA8AQIoQRKrOQ/6hasVVS7zPT80twfAyxmawjhjqYFUacyx2yqz1qOeCKHsYhKPk/VwgF15V7CwddPNvBlDTw==", + "requires": { + "n3": "^1.0.0-beta.1" + }, + "dependencies": { + "n3": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/n3/-/n3-1.0.0-beta.2.tgz", + "integrity": "sha512-dY0Q21JhNJozPMSijKI9phfgocXb7hF9F8zOPnsRu0Dy61eQwQVKcFEw59V0sn2F/neJjNg7WHmNtGLMkPpKPA==" + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "realpath-native": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.2.tgz", + "integrity": "sha512-+S3zTvVt9yTntFrBpm7TQmQ3tzpCrnA1a/y+3cUHAc9ZR6aIjG0WNLR+Rj79QpJktY+VeW/TQtFlQ1bzsehI8g==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "reflect-metadata": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", + "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "^4.13.1" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rsvp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", + "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sane": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz", + "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "capture-exit": "^1.2.0", + "exec-sh": "^0.2.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.3", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5", + "watch": "~0.18.0" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", + "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + }, + "serialize-javascript": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", + "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sisteransi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", + "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spawn-sync": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", + "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", + "dev": true, + "requires": { + "concat-stream": "^1.4.7", + "os-shim": "^0.1.2" + } + }, + "spdx-correct": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" + }, + "tapable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", + "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==", + "dev": true + }, + "test-exclude": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", + "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "micromatch": "^2.3.11", + "object-assign": "^4.1.0", + "read-pkg-up": "^1.0.1", + "require-main-filename": "^1.0.1" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "ts-jest": { + "version": "23.10.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-23.10.4.tgz", + "integrity": "sha512-oV/wBwGUS7olSk/9yWMiSIJWbz5xO4zhftnY3gwv6s4SMg6WHF1m8XZNBvQOKQRiTAexZ9754Z13dxBq3Zgssw==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "json5": "2.x", + "make-error": "1.x", + "mkdirp": "0.x", + "semver": "^5.5", + "yargs-parser": "10.x" + }, + "dependencies": { + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "ts-loader": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.3.0.tgz", + "integrity": "sha512-lGSNs7szRFj/rK9T1EQuayE3QNLg6izDUxt5jpmq0RG1rU2bapAt7E7uLckLCUPeO1jwxCiet2oRaWovc53UAg==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^3.1.4", + "semver": "^5.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, + "tslint": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", + "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typedoc": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.13.0.tgz", + "integrity": "sha512-jQWtvPcV+0fiLZAXFEe70v5gqjDO6pJYJz4mlTtmGJeW2KRoIU/BEfktma6Uj8Xii7UakuZjbxFewl3UYOkU/w==", + "dev": true, + "requires": { + "@types/fs-extra": "^5.0.3", + "@types/handlebars": "^4.0.38", + "@types/highlight.js": "^9.12.3", + "@types/lodash": "^4.14.110", + "@types/marked": "^0.4.0", + "@types/minimatch": "3.0.3", + "@types/shelljs": "^0.8.0", + "fs-extra": "^7.0.0", + "handlebars": "^4.0.6", + "highlight.js": "^9.0.0", + "lodash": "^4.17.10", + "marked": "^0.4.0", + "minimatch": "^3.0.0", + "progress": "^2.0.0", + "shelljs": "^0.8.2", + "typedoc-default-themes": "^0.5.0", + "typescript": "3.1.x" + } + }, + "typedoc-default-themes": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz", + "integrity": "sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=", + "dev": true + }, + "typescript": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", + "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", + "dev": true + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true, + "optional": true + } + } + }, + "uglifyjs-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "dev": true, + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "schema-utils": "^0.4.5", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "uglify-es": "^3.3.4", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + } + } + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "uritemplate": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/uritemplate/-/uritemplate-0.3.4.tgz", + "integrity": "sha1-BdCoU/+8iw9Jqj1NKtd3sNHuBww=" + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "v8-compile-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", + "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, + "watch": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", + "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", + "dev": true, + "requires": { + "exec-sh": "^0.2.0", + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "webpack": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.25.1.tgz", + "integrity": "sha512-T0GU/3NRtO4tMfNzsvpdhUr8HnzA4LTdP2zd+e5zd6CdOH5vNKHnAlO+DvzccfhPdzqRrALOFcjYxx7K5DWmvA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/wasm-edit": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "acorn": "^5.6.2", + "acorn-dynamic-import": "^3.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^0.4.4", + "tapable": "^1.1.0", + "uglifyjs-webpack-plugin": "^1.2.4", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", + "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "webpack-cli": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.2.tgz", + "integrity": "sha512-Cnqo7CeqeSvC6PTdts+dywNi5CRlIPbLx1AoUPK2T6vC1YAugMG3IOoO9DmEscd+Dghw7uRlnzV1KwOe5IrtgQ==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.0", + "global-modules-path": "^2.3.0", + "import-local": "^2.0.0", + "interpret": "^1.1.0", + "loader-utils": "^1.1.0", + "supports-color": "^5.5.0", + "v8-compile-cache": "^2.0.2", + "yargs": "^12.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "dev": true, + "requires": { + "xregexp": "4.0.0" + } + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", + "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" + } + }, + "os-locale": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", + "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "dev": true, + "requires": { + "execa": "^0.10.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", + "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^2.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^10.1.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, + "whatwg-mimetype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz", + "integrity": "sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw==" + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "wreck": { + "version": "12.5.1", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-12.5.1.tgz", + "integrity": "sha512-l5DUGrc+yDyIflpty1x9XuMj1ehVjC/dTbF3/BasOO77xk0EdEa4M/DuOY8W88MQDAD0fEDqyjc8bkIMHd2E9A==", + "requires": { + "boom": "5.x.x", + "hoek": "4.x.x" + } + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + }, + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "11.1.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } +} diff --git a/package.json b/package.json index 78eefe01..0892dff5 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,56 @@ { "name": "plannerjs", - "version": "1.0.0", - "description": "", - "main": "dist/index.js", - "types": "dist/index.d.ts", + "version": "0.0.1", + "description": "The JavaScript framework for journey planning.", + "main": "lib/index.js", + "license": "MIT", + "repository": { + "type": "git", + "url": "git://github.com/openplannerteam/planner.js.git" + }, + "bugs": { + "url": "https://github.com/openplannerteam/planner.js/issues" + }, + "browser": "dist/bundle.js", + "types": "lib/index.d.ts", "scripts": { + "test": "jest", + "debug": "ndb node lib/demo.cli.js --debug", "build": "tsc", - "test": "jest" + "browser": "npm run webpack", + "lint": "./node_modules/tslint/bin/tslint --project .", + "webpack": "webpack --config webpack.config.js --mode=production", + "webpack-stats": "npm run webpack -- --display-modules --json > stats.json", + "typedoc": "typedoc --options typedoc.js", + "doc": "npm run typedoc & npm run browser && cp dist/bundle.js docs/js/planner-latest.js && cp dist/bundle.js.map docs/js/planner-latest.js.map" }, "dependencies": { + "asynciterator": "^2.0.1", "haversine": "^1.1.0", "inversify": "^5.0.1", "isomorphic-fetch": "^2.2.1", "ldfetch": "^1.1.1-alpha", "n3": "0.11.2", "reflect-metadata": "^0.1.12", - "typescript": "^3.1.3", "uritemplate": "^0.3.4" }, + "pre-commit": [ + "lint" + ], "devDependencies": { + "@types/asynciterator": "^1.1.1", "@types/haversine": "^1.1.0", "@types/jest": "^23.3.7", "@types/rdf-js": "^1.0.1", "jest": "^23.6.0", + "pre-commit": "^1.2.2", "prettier": "1.14.3", "ts-jest": "^23.10.4", - "tslint": "^5.11.0" + "ts-loader": "^5.3.0", + "tslint": "^5.11.0", + "typedoc": "^0.13.0", + "typescript": "^3.1.6", + "webpack": "^4.25.1", + "webpack-cli": "^3.1.2" } } diff --git a/src/Catalog.ts b/src/Catalog.ts new file mode 100644 index 00000000..6bfebad8 --- /dev/null +++ b/src/Catalog.ts @@ -0,0 +1,14 @@ +import TravelMode from "./TravelMode"; + +export default class Catalog { + public stopsFetcherConfigs = []; + public connectionsFetcherConfigs = []; + + public addStopsFetcher(prefix: string, accessUrl: string) { + this.stopsFetcherConfigs.push({prefix, accessUrl}); + } + + public addConnectionsFetcher(accessUrl: string, travelMode: TravelMode) { + this.connectionsFetcherConfigs.push({accessUrl, travelMode}); + } +} diff --git a/src/Defaults.ts b/src/Defaults.ts new file mode 100644 index 00000000..0406b800 --- /dev/null +++ b/src/Defaults.ts @@ -0,0 +1,8 @@ +import Units from "./util/Units"; + +export default class Defaults { + public static readonly defaultMinimumWalkingSpeed = 3; + public static readonly defaultMaximumWalkingSpeed = 6; + public static readonly defaultMaximumTransferDuration = Units.fromHours(.4); + public static readonly defaultMaximumTransfers = 8; +} diff --git a/src/Planner.ts b/src/Planner.ts index 236959e9..d20bcc79 100644 --- a/src/Planner.ts +++ b/src/Planner.ts @@ -1,6 +1,7 @@ +import { AsyncIterator } from "asynciterator"; import Context from "./Context"; +import IPath from "./interfaces/IPath"; import IQuery from "./interfaces/IQuery"; -import IQueryResult from "./interfaces/IQueryResult"; import defaultContainer from "./inversify.config"; import IQueryRunner from "./query-runner/IQueryRunner"; import TYPES from "./types"; @@ -9,10 +10,17 @@ if (!Symbol.asyncIterator) { (Symbol as any).asyncIterator = Symbol.for("Symbol.asyncIterator"); } +/** + * Allows to ask route planning queries over our knowledge graphs + */ export default class Planner { private context: Context; private queryRunner: IQueryRunner; + /** + * Initializes a new Planner + * @param container The container of dependencies we are working with + */ constructor(container = defaultContainer) { // Store container on context before doing anything else this.context = container.get(TYPES.Context); @@ -21,7 +29,12 @@ export default class Planner { this.queryRunner = container.get(TYPES.QueryRunner); } - public async query(query: IQuery): Promise { + /** + * Given an [[IQuery]], it will evaluate the query and eventually produce an [[IQueryResult]] + * @param query An [[IQuery]] specifying a route planning query + * @returns An AsyncIterator of [[IPath]]s + */ + public async query(query: IQuery): Promise> { return this.queryRunner.run(query); } } diff --git a/src/TravelMode.ts b/src/TravelMode.ts new file mode 100644 index 00000000..eba28087 --- /dev/null +++ b/src/TravelMode.ts @@ -0,0 +1,7 @@ +enum TravelMode { + Train = "train", + Bus = "bus", + Walking = "walking", +} + +export default TravelMode; diff --git a/src/demo.cli.ts b/src/demo.cli.ts new file mode 100644 index 00000000..d9bb265e --- /dev/null +++ b/src/demo.cli.ts @@ -0,0 +1,13 @@ +import runDemo from "./demo"; + +const isDebugging = process && process.argv.includes("--debug"); + +(async () => { + if (isDebugging) { // tslint:disable-next-line:no-debugger + debugger; + } + + runDemo(true) + .then(() => console.log("Success")) + .catch((e) => console.error(e)); +})(); diff --git a/src/demo.test.ts b/src/demo.test.ts new file mode 100644 index 00000000..dc20a4cc --- /dev/null +++ b/src/demo.test.ts @@ -0,0 +1,10 @@ +import "jest"; +import runDemo from "./demo"; + +test("demo", async () => { + jest.setTimeout(90000); + + const result = await runDemo(false); + + expect(result).toEqual(true); +}); diff --git a/src/demo.ts b/src/demo.ts new file mode 100644 index 00000000..3d770876 --- /dev/null +++ b/src/demo.ts @@ -0,0 +1,45 @@ +import Planner from "./index"; +import Units from "./util/Units"; + +export default async (logResults) => { + + const planner = new Planner(); + + // const roadOnlyResult = await planner.query({ + // roadOnly: true, + // from: "http://irail.be/stations/NMBS/008896008", // Kortrijk + // to: "http://irail.be/stations/NMBS/008892007", // Ghent-Sint-Pieters + // }); +// + // roadOnlyResult.each((path) => { + // if (logResults) { + // console.log(path); + // } + // }); + + console.time("Public transport planner"); + + const publicTransportResult = await planner.query({ + publicTransportOnly: true, + from: "http://irail.be/stations/NMBS/008896925", // Ingelmunster + to: "http://irail.be/stations/NMBS/008892007", // Ghent-Sint-Pieters + minimumDepartureTime: new Date(), + maximumTransferDuration: Units.fromHours(.5), + }); + + console.timeEnd("Public transport planner"); + + let i = 0; + + publicTransportResult.on("readable", () => { + let path = publicTransportResult.read(); + + while (path && i < 5) { + console.log(i++, path); + + path = publicTransportResult.read(); + } + }); + + return true; +}; diff --git a/src/fetcher/connections/ConnectionsProviderPassthrough.ts b/src/fetcher/connections/ConnectionsProviderPassthrough.ts new file mode 100644 index 00000000..6c3e754b --- /dev/null +++ b/src/fetcher/connections/ConnectionsProviderPassthrough.ts @@ -0,0 +1,34 @@ +import { AsyncIterator } from "asynciterator"; +import { inject, injectable } from "inversify"; +import Catalog from "../../Catalog"; +import TYPES, { ConnectionsFetcherFactory } from "../../types"; +import IConnection from "./IConnection"; +import IConnectionsFetcher from "./IConnectionsFetcher"; +import IConnectionsFetcherConfig from "./IConnectionsFetcherConfig"; +import IConnectionsProvider from "./IConnectionsProvider"; + +/** + * Passes through one [[IConnectionsFetcher]], the first one if there are multiple + */ +@injectable() +export default class ConnectionsProviderPassthrough implements IConnectionsProvider { + + private readonly connectionsFetcher: IConnectionsFetcher; + + constructor( + @inject(TYPES.ConnectionsFetcherFactory) connectionsFetcherFactory: ConnectionsFetcherFactory, + @inject(TYPES.Catalog) catalog: Catalog, + ) { + const { accessUrl, travelMode } = catalog.connectionsFetcherConfigs[0]; + + this.connectionsFetcher = connectionsFetcherFactory(accessUrl, travelMode); + } + + public createIterator(): AsyncIterator { + return this.connectionsFetcher.createIterator(); + } + + public setConfig(config: IConnectionsFetcherConfig): void { + this.connectionsFetcher.setConfig(config); + } +} diff --git a/src/fetcher/connections/DropOffType.ts b/src/fetcher/connections/DropOffType.ts new file mode 100644 index 00000000..7187019c --- /dev/null +++ b/src/fetcher/connections/DropOffType.ts @@ -0,0 +1,8 @@ +enum DropOffType { + Regular = "gtfs:Regular", + NotAvailable = "gtfs:NotAvailable", + MustPhone = "gtfs:MustPhone", + MustCoordinateWithDriver = "gtfs:MustCoordinateWithDriver", +} + +export default DropOffType; diff --git a/src/fetcher/connections/IConnection.ts b/src/fetcher/connections/IConnection.ts index 8b1c1e0c..1be060e7 100644 --- a/src/fetcher/connections/IConnection.ts +++ b/src/fetcher/connections/IConnection.ts @@ -1,13 +1,36 @@ +import { DurationMs } from "../../interfaces/units"; +import TravelMode from "../../TravelMode"; +import DropOffType from "./DropOffType"; +import PickupType from "./PickupType"; + +/** + * Interface for a Connection. This describes an actual transport vehicle going from its + * departureStop to its arrivalStop at a certain departureTime, arriving at the arrivalTime. + * The arrivalTime and departureTime already include the delay and are the actual real-time values + * for the actual arrival and departureTime. + * The arrivalDelay and departureDelay then again contain the duration in which these times deviate + * from the planned time. + * @property "gtfs:trip" (optional) an identifier for the trip this vehicle is making with this connection + * @property nextConnection (optional) an identifier for the next connection the vehicle is going to make + * @property TravelMode The type of vehicle that is used, chosen from an enum [[TravelMode]] + */ export default interface IConnection { - "@id": string; + id: string; + travelMode: TravelMode; arrivalTime: Date; arrivalStop: string; - arrivalDelay: number; + arrivalDelay?: DurationMs; departureTime: Date; departureStop: string; - departureDelay: number; + departureDelay?: DurationMs; + + nextConnection?: string[]; - "gtfs:trip": string; + "gtfs:route"?: string; + "gtfs:trip"?: string; + "gtfs:dropOffType"?: DropOffType; + "gtfs:pickupType"?: PickupType; + "gtfs:headsign"?: string; } diff --git a/src/fetcher/connections/IConnectionsFetcher.ts b/src/fetcher/connections/IConnectionsFetcher.ts index 78007356..194b6e8d 100644 --- a/src/fetcher/connections/IConnectionsFetcher.ts +++ b/src/fetcher/connections/IConnectionsFetcher.ts @@ -1,6 +1,8 @@ -import IConnection from "./IConnection"; -import IConnectionsFetcherConfig from "./IConnectionsFetcherConfig"; +import IConnectionsProvider from "./IConnectionsProvider"; -export default interface IConnectionsFetcher extends AsyncIterable { - setConfig: (config: IConnectionsFetcherConfig) => void; +/** + * Entry point for fetching linked connections ([[IConnection]]s) + * Serves as interface for dependency injection, so all implementations should have @injectable() decorator + */ +export default interface IConnectionsFetcher extends IConnectionsProvider { } diff --git a/src/fetcher/connections/IConnectionsFetcherConfig.ts b/src/fetcher/connections/IConnectionsFetcherConfig.ts index 1c8d48a1..cbb27f2d 100644 --- a/src/fetcher/connections/IConnectionsFetcherConfig.ts +++ b/src/fetcher/connections/IConnectionsFetcherConfig.ts @@ -1,5 +1,5 @@ export default interface IConnectionsFetcherConfig { - upperBoundDate?: Date, - lowerBoundDate?: Date, + upperBoundDate?: Date; + lowerBoundDate?: Date; backward?: boolean; } diff --git a/src/fetcher/connections/IConnectionsProvider.ts b/src/fetcher/connections/IConnectionsProvider.ts new file mode 100644 index 00000000..7d89c6c7 --- /dev/null +++ b/src/fetcher/connections/IConnectionsProvider.ts @@ -0,0 +1,13 @@ +import { AsyncIterator } from "asynciterator"; +import IConnection from "./IConnection"; +import IConnectionsFetcherConfig from "./IConnectionsFetcherConfig"; + +/** + * A IConnectionsProvider serves as interface to other classes that want to use [[IConnection]] instances + * It does this by acting as a transparent proxy between the user class and the configured [[IConnectionFetcher]] + * instances + */ +export default interface IConnectionsProvider { + createIterator: () => AsyncIterator; + setConfig: (config: IConnectionsFetcherConfig) => void; +} diff --git a/src/fetcher/connections/PickupType.ts b/src/fetcher/connections/PickupType.ts new file mode 100644 index 00000000..537a8b15 --- /dev/null +++ b/src/fetcher/connections/PickupType.ts @@ -0,0 +1,8 @@ +enum PickupType { + Regular = "gtfs:Regular", + NotAvailable = "gtfs:NotAvailable", + MustPhone = "gtfs:MustPhone", + MustCoordinateWithDriver = "gtfs:MustCoordinateWithDriver", +} + +export default PickupType; diff --git a/src/fetcher/connections/comunica/ConnectionsFetcherComunica.ts b/src/fetcher/connections/comunica/ConnectionsFetcherComunica.ts deleted file mode 100644 index 8de806e5..00000000 --- a/src/fetcher/connections/comunica/ConnectionsFetcherComunica.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { injectable } from "inversify"; -import IConnection from "../IConnection"; -import IConnectionsFetcher from "../IConnectionsFetcher"; -import IConnectionsFetcherConfig from "../IConnectionsFetcherConfig"; - -@injectable() -export default class ConnectionsFetcherComunica implements IConnectionsFetcher { - public fetch: () => AsyncIterator; - public setConfig: (config: IConnectionsFetcherConfig) => void; - - public [Symbol.asyncIterator](): AsyncIterator { - return undefined; - } - -} diff --git a/src/fetcher/connections/ld-fetch/ConnectionsFetcherDeLijn.ts b/src/fetcher/connections/ld-fetch/ConnectionsFetcherDeLijn.ts deleted file mode 100644 index fcd28bf8..00000000 --- a/src/fetcher/connections/ld-fetch/ConnectionsFetcherDeLijn.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { injectable } from "inversify"; -import IConnection from "../IConnection"; -import ConnectionsFetcherLDFetch from "./ConnectionsFetcherLDFetch"; -import ConnectionsIteratorLDFetch from "./ConnectionsIteratorLDFetch"; - -const DE_LIJN_BASE_URL = "http://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/connections"; - -@injectable() -export default class ConnectionsFetcherDeLijn extends ConnectionsFetcherLDFetch { - - public fetch(): AsyncIterator { - return new ConnectionsIteratorLDFetch( - DE_LIJN_BASE_URL, - this.ldFetch, - this.config, - ); - } -} diff --git a/src/fetcher/connections/ld-fetch/ConnectionsFetcherLDFetch.ts b/src/fetcher/connections/ld-fetch/ConnectionsFetcherLDFetch.ts deleted file mode 100644 index ef3aff68..00000000 --- a/src/fetcher/connections/ld-fetch/ConnectionsFetcherLDFetch.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { injectable } from "inversify"; -import LdFetch from "ldfetch"; -import IConnection from "../IConnection"; -import IConnectionsFetcher from "../IConnectionsFetcher"; -import IConnectionsFetcherConfig from "../IConnectionsFetcherConfig"; - - -@injectable() -export default abstract class ConnectionsFetcherLDFetch implements IConnectionsFetcher { - - protected readonly ldFetch: LdFetch; - protected config: IConnectionsFetcherConfig; - - constructor() { - this.ldFetch = new LdFetch(); - this.setupDebug(); - } - - public [Symbol.asyncIterator](): AsyncIterator { - return this.fetch(); - } - - public abstract fetch(): AsyncIterator; - - public setConfig(config: IConnectionsFetcherConfig): void { - this.config = config; - } - - private setupDebug() { - const httpStartTimes = {}; - const httpResponseTimes = {}; - - this.ldFetch.on("request", (url) => { - httpStartTimes[url] = new Date(); - }); - - this.ldFetch.on("redirect", (obj) => { - httpStartTimes[obj.to] = httpStartTimes[obj.from]; - }); - - this.ldFetch.on("response", (url) => { - httpResponseTimes[url] = (new Date()).getTime() - httpStartTimes[url].getTime(); - console.error(`HTTP GET - ${url} (${httpResponseTimes[url]}ms)`); - }); - } -} diff --git a/src/fetcher/connections/ld-fetch/ConnectionsFetcherLazy.ts b/src/fetcher/connections/ld-fetch/ConnectionsFetcherLazy.ts new file mode 100644 index 00000000..18dd7e66 --- /dev/null +++ b/src/fetcher/connections/ld-fetch/ConnectionsFetcherLazy.ts @@ -0,0 +1,47 @@ +import { AsyncIterator } from "asynciterator"; +import { inject, injectable } from "inversify"; +import LDFetch from "ldfetch"; +import TravelMode from "../../../TravelMode"; +import TYPES from "../../../types"; +import IConnection from "../IConnection"; +import IConnectionsFetcher from "../IConnectionsFetcher"; +import IConnectionsFetcherConfig from "../IConnectionsFetcherConfig"; +import ConnectionsIteratorLazy from "./ConnectionsIteratorLazy"; + +/** + * Wraps the [[ConnectionsIteratorLazy]] + * @implements IConnectionsFetcher + */ +@injectable() +export default class ConnectionsFetcherLazy implements IConnectionsFetcher { + + protected readonly ldFetch: LDFetch; + protected config: IConnectionsFetcherConfig; + private travelMode: TravelMode; + private accessUrl: string; + + constructor(@inject(TYPES.LDFetch) ldFetch: LDFetch) { + this.ldFetch = ldFetch; + } + + public setTravelMode(travelMode: TravelMode) { + this.travelMode = travelMode; + } + + public setAccessUrl(accessUrl: string) { + this.accessUrl = accessUrl; + } + + public createIterator(): AsyncIterator { + return new ConnectionsIteratorLazy( + this.accessUrl, + this.travelMode, + this.ldFetch, + this.config, + ); + } + + public setConfig(config: IConnectionsFetcherConfig): void { + this.config = config; + } +} diff --git a/src/fetcher/connections/ld-fetch/ConnectionsFetcherNMBS.ts b/src/fetcher/connections/ld-fetch/ConnectionsFetcherNMBS.ts deleted file mode 100644 index 8ddf8de1..00000000 --- a/src/fetcher/connections/ld-fetch/ConnectionsFetcherNMBS.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { injectable } from "inversify"; -import IConnection from "../IConnection"; -import ConnectionsFetcherLDFetch from "./ConnectionsFetcherLDFetch"; -import ConnectionsIteratorLDFetch from "./ConnectionsIteratorLDFetch"; - -const IRAIL_CONNECTIONS_BASE_URL = "https://graph.irail.be/sncb/connections"; - -@injectable() -export default class ConnectionsFetcherNMBS extends ConnectionsFetcherLDFetch { - - public fetch(): AsyncIterator { - return new ConnectionsIteratorLDFetch( - IRAIL_CONNECTIONS_BASE_URL, - this.ldFetch, - this.config, - ); - } -} diff --git a/src/fetcher/connections/ld-fetch/ConnectionsIteratorLDFetch.test.ts b/src/fetcher/connections/ld-fetch/ConnectionsIteratorLDFetch.test.ts deleted file mode 100644 index b66dca01..00000000 --- a/src/fetcher/connections/ld-fetch/ConnectionsIteratorLDFetch.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import "jest"; -import LdFetch from "ldfetch"; -import ConnectionsIteratorLDFetch from "./ConnectionsIteratorLDFetch"; - -const CONNECTIONS_TO_LOAD = 200; // Should be more than contained on first page - -test("[ConnectionsIteratorLDFetch] iterate forwards", async () => { - - const config = { - backward: false, - lowerBoundDate: new Date(2018, 10, 2, 10), - }; - const iterator = new ConnectionsIteratorLDFetch("https://graph.irail.be/sncb/connections", new LdFetch(), config); - - const dummyIterable = { - [Symbol.asyncIterator]: () => iterator, - }; - - let i = 0; - let lastConnection; - - for await (const connection of dummyIterable) { - - if (!lastConnection) { - lastConnection = connection; - continue; - } - - expect(connection.departureTime.valueOf()).toBeGreaterThanOrEqual(lastConnection.departureTime.valueOf()); - - lastConnection = connection; - - if (i++ === CONNECTIONS_TO_LOAD) { - break; - } - } -}); diff --git a/src/fetcher/connections/ld-fetch/ConnectionsIteratorLDFetch.ts b/src/fetcher/connections/ld-fetch/ConnectionsIteratorLDFetch.ts deleted file mode 100644 index cc942386..00000000 --- a/src/fetcher/connections/ld-fetch/ConnectionsIteratorLDFetch.ts +++ /dev/null @@ -1,210 +0,0 @@ -import LdFetch from "ldfetch"; -import { Util } from "n3"; -import { Triple } from "rdf-js"; -import UriTemplate from "uritemplate"; -import { matchesTriple, transformPredicate } from "../../helpers"; -import IConnection from "../IConnection"; -import IConnectionsFetcherConfig from "../IConnectionsFetcherConfig"; - -interface IEntity { -} - -interface IEntityMap { - [subject: string]: IEntity; -} - -export default class ConnectionsIteratorLDFetch implements AsyncIterator { - public readonly baseUrl: string; - private ldFetch: LdFetch; - - private connections: IConnection[]; - private config: IConnectionsFetcherConfig; - - private previousPageIri: string; - private nextPageIri: string; - - constructor( - baseUrl: string, - ldFetch: LdFetch, - config: IConnectionsFetcherConfig, - ) { - this.baseUrl = baseUrl; - this.ldFetch = ldFetch; - this.config = config; - } - - public getNextPageIri(): string { - return this.nextPageIri; - } - - public getPreviousPageIri(): string { - return this.previousPageIri; - } - - public getConnections(): IConnection[] { - return this.connections; - } - - public async next(): Promise> { - if (!this.connections) { - await this.discover(); - - } else if (this.connections.length === 0) { - const pageIri = this.config.backward ? - this.previousPageIri : this.nextPageIri; - - await this.loadPage(pageIri); - } - - const value = this.config.backward ? - this.connections.pop() : - this.connections.shift(); - - return { value, done: false }; - - } - - public return(): Promise> { - return undefined; - } - - public throw(e?: any): Promise> { - return undefined; - } - - private filterConnectionsFromEntities(entities: IEntityMap): IConnection[] { - const typePredicate = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; - - // building block 2: every lc:Connection entity is taken from the page and processed - return Object.values(entities) - .filter((entity: IEntity) => - entity[typePredicate] && entity[typePredicate] === "http://semweb.mmlab.be/ns/linkedconnections#Connection", - ) as IConnection[]; - } - - private addTriples(documentIri: string, triples: Triple[]) { - - // Find next page - this.setHydraLinks(triples, documentIri); - - // group all entities together and - const entities = this.getEntities(triples); - - // Find all Connections - const connections = this.filterConnectionsFromEntities(entities); - - // Sort connections by departure time - this.connections = connections.sort((connectionA, connectionB) => { - return connectionA.departureTime.valueOf() - connectionB.departureTime.valueOf(); - }); - } - - private transformPredicate(triple: Triple): Triple { - return transformPredicate({ - "http://semweb.mmlab.be/ns/linkedconnections#departureTime": "departureTime", - "http://semweb.mmlab.be/ns/linkedconnections#departureDelay": "departureDelay", - "http://semweb.mmlab.be/ns/linkedconnections#arrivalDelay": "arrivalDelay", - "http://semweb.mmlab.be/ns/linkedconnections#arrivalTime": "arrivalTime", - "http://semweb.mmlab.be/ns/linkedconnections#departureStop": "departureStop", - "http://semweb.mmlab.be/ns/linkedconnections#arrivalStop": "arrivalStop", - "http://vocab.gtfs.org/terms#trip": "gtfs:trip", - }, triple); - } - - private getEntities(triples: Triple[]): IEntityMap { - - return triples.reduce((entities: IEntityMap, triple: Triple) => { - triple = this.transformPredicate(triple); - - const { subject: { value: subject }, predicate: { value: predicate }, object: { value: object } } = triple; - let newObject; - - if (triple.predicate.value === "departureTime" || triple.predicate.value === "arrivalTime") { - newObject = new Date(triple.object.value); - } - - if (!entities[subject]) { - entities[subject] = { - ["@id"]: subject, - }; - } - - entities[subject][predicate] = newObject || object; - - return entities; - }, {}); - } - - private async discover(): Promise { - await this.ldFetch.get(this.baseUrl) - .then(async (response) => { - - const metaTriples = this.getHydraTriples(response.triples); - const searchTemplate = this.getHydraSearchTemplate(metaTriples, response.url); - - const departureTimeDate = this.config.backward ? - this.config.upperBoundDate : this.config.lowerBoundDate; - - const firstPageIri = searchTemplate.expand({ - departureTime: departureTimeDate.toISOString(), - }); - - await this.loadPage(firstPageIri); - }); - } - - private getHydraTriples(triples: Triple[]): Triple[] { - return triples.filter((triple) => { - return ( - triple.predicate.value === "http://www.w3.org/ns/hydra/core#search" || - triple.predicate.value === "http://www.w3.org/ns/hydra/core#mapping" || - triple.predicate.value === "http://www.w3.org/ns/hydra/core#template" || - triple.predicate.value === "http://www.w3.org/ns/hydra/core#property" || - triple.predicate.value === "http://www.w3.org/ns/hydra/core#variable" - ); - }); - } - - private getHydraSearchTemplate(hydraTriples: Triple[], searchUri): UriTemplate { - const searchTriple = hydraTriples.find( - matchesTriple(searchUri, "http://www.w3.org/ns/hydra/core#search", null), - ); - - const templateTriple = hydraTriples.find( - matchesTriple(searchTriple.object.value, "http://www.w3.org/ns/hydra/core#template", null), - ); - - const template = templateTriple.object.value; - return UriTemplate.parse(template); - - } - - private setHydraLinks(triples: Triple[], documentIri: string): void { - - // building block 1: every page should be a hydra:PagedCollection with a next and previous page link - const nextPageTriple: Triple = triples.find( - matchesTriple(documentIri, "http://www.w3.org/ns/hydra/core#next", null), - ); - const previousPageTriple: Triple = triples.find( - matchesTriple(documentIri, "http://www.w3.org/ns/hydra/core#previous", null), - ); - - this.nextPageIri = null; - this.previousPageIri = null; - - if (nextPageTriple && nextPageTriple.object.value.substr(0, 4) === "http") { - this.nextPageIri = nextPageTriple.object.value; - } - - if (previousPageTriple && previousPageTriple.object.value.substr(0, 4) === "http") { - this.previousPageIri = previousPageTriple.object.value; - } - } - - private async loadPage(url: string) { - await this.ldFetch.get(url) - .then((response) => { - this.addTriples(response.url, response.triples); - }); - } -} diff --git a/src/fetcher/connections/ld-fetch/ConnectionsIteratorLazy.test.ts b/src/fetcher/connections/ld-fetch/ConnectionsIteratorLazy.test.ts new file mode 100644 index 00000000..3195d75c --- /dev/null +++ b/src/fetcher/connections/ld-fetch/ConnectionsIteratorLazy.test.ts @@ -0,0 +1,44 @@ +import "jest"; +import LdFetch from "ldfetch"; +import TravelMode from "../../../TravelMode"; +import IConnection from "../IConnection"; +import ConnectionsIteratorLazy from "./ConnectionsIteratorLazy"; + +const CONNECTIONS_TO_LOAD = 500; // Should be more than contained on first page + +test("[ConnectionsIteratorLazy] iterate forwards", (done) => { + jest.setTimeout(90000); + + const config = { + backward: false, + lowerBoundDate: new Date(2018, 10, 22, 10), + }; + const iterator = new ConnectionsIteratorLazy( + "https://graph.irail.be/sncb/connections", + TravelMode.Train, + new LdFetch(), + config, + ); + + let i = 0; + let lastConnection: IConnection; + + iterator.on("readable", () => { + lastConnection = iterator.read(); + let connection = iterator.read(); + + while (connection && i++ < CONNECTIONS_TO_LOAD) { + + expect(connection.departureTime.valueOf()).toBeGreaterThanOrEqual(lastConnection.departureTime.valueOf()); + + lastConnection = connection; + connection = iterator.read(); + } + + if (i >= CONNECTIONS_TO_LOAD) { + iterator.close(); + done(); + } + }); + +}); diff --git a/src/fetcher/connections/ld-fetch/ConnectionsIteratorLazy.ts b/src/fetcher/connections/ld-fetch/ConnectionsIteratorLazy.ts new file mode 100644 index 00000000..d1760dd0 --- /dev/null +++ b/src/fetcher/connections/ld-fetch/ConnectionsIteratorLazy.ts @@ -0,0 +1,106 @@ +import { BufferedIterator } from "asynciterator"; +import LdFetch from "ldfetch"; +import UriTemplate from "uritemplate"; +import TravelMode from "../../../TravelMode"; +import IConnection from "../IConnection"; +import IConnectionsFetcherConfig from "../IConnectionsFetcherConfig"; +import HydraPageParser from "./HydraPageParser"; +import IHydraPage from "./IHydraPage"; + +/** + * Base class for fetching linked connections with LDFetch and letting the caller iterate over them asynchronously + * through implementing the AsyncIterator protocol. + * LDFetch returns documents as an array of RDF triples. + * The meta Hydra triples are used for paginating to the next or previous page. + * The triples that describe linked connections get deserialized to instances of [[IConnection]] + */ +export default class ConnectionsIteratorLazy extends BufferedIterator { + private readonly baseUrl: string; + private readonly travelMode: TravelMode; + private readonly ldFetch: LdFetch; + private readonly config: IConnectionsFetcherConfig; + + private currentPage: IHydraPage; + + constructor( + baseUrl: string, + travelMode: TravelMode, + ldFetch: LdFetch, + config: IConnectionsFetcherConfig, + ) { + super({ + autoStart: true, + }); + + this.baseUrl = baseUrl; + this.travelMode = travelMode; + this.ldFetch = ldFetch; + this.config = config; + } + + public _begin(done: () => void): void { + this.ldFetch.get(this.baseUrl) + .then((response) => { + const parser = new HydraPageParser(response.triples); + const searchTemplate: UriTemplate = parser.getSearchTemplate(); + + const departureTimeDate = this.config.backward ? + this.config.upperBoundDate : this.config.lowerBoundDate; + + const firstPageIri = searchTemplate.expand({ + departureTime: departureTimeDate.toISOString(), + }); + + this.loadPage(firstPageIri) + .then(() => done()); + }); + } + + public _read(count: number, done: () => void): void { + + const pageIri = this.config.backward ? + this.currentPage.previousPageIri : this.currentPage.nextPageIri; + + this.loadPage(pageIri) + .then(() => done()); + } + + private async loadPage(url: string) { + await this.ldFetch.get(url) + .then((response) => { + + const parser = new HydraPageParser(response.triples); + const page = parser.getPage(0, this.travelMode); + + if (this.config.backward) { + page.previousPageIri = parser.getPreviousPageIri(); + + } else { + page.nextPageIri = parser.getNextPageIri(); + } + + this.currentPage = page; + this.pushCurrentPage(); + }); + } + + private pushCurrentPage(): void { + const { connections } = this.currentPage; + + if (this.config.backward) { + let c = connections.length - 1; + + while (c >= 0) { + this._push(connections[c]); + c--; + } + + // Forwards + } else { + for (const connection of connections) { + this._push(connection); + } + } + } + +} diff --git a/src/fetcher/connections/ld-fetch/ConnectionsPageParser.ts b/src/fetcher/connections/ld-fetch/ConnectionsPageParser.ts new file mode 100644 index 00000000..a3a25fe9 --- /dev/null +++ b/src/fetcher/connections/ld-fetch/ConnectionsPageParser.ts @@ -0,0 +1,136 @@ +import { Triple } from "rdf-js"; +import TravelMode from "../../../TravelMode"; +import Rdf from "../../../util/Rdf"; +import Units from "../../../util/Units"; +import DropOffType from "../DropOffType"; +import IConnection from "../IConnection"; +import PickupType from "../PickupType"; + +interface IEntity { +} + +interface IEntityMap { + [subject: string]: IEntity; +} + +/** + * Parses the given array of triples into an array of [[IConnection]]s + * It first builds up an array of entities, where each item is a 'subject', + * its properties are 'predicates' and values are 'objects' + * After, it filters those entities by type, only leaving 'linked connections'. + */ +export default class ConnectionsPageParser { + private readonly documentIri: string; + private readonly triples: Triple[]; + + constructor(documentIri: string, triples: Triple[]) { + this.documentIri = documentIri; + this.triples = triples; + } + + public getConnections(travelMode: TravelMode): IConnection[] { + // group all entities together and + const entities = this.getEntities(this.triples); + + // Find all Connections + let connections = this.filterConnectionsFromEntities(entities); + + // Add travel mode + connections = connections.map((connection: IConnection) => { + connection.travelMode = travelMode; + return connection; + }); + + // Sort connections by departure time + return connections.sort((connectionA, connectionB) => { + return connectionA.departureTime.valueOf() - connectionB.departureTime.valueOf(); + }); + } + + private filterConnectionsFromEntities(entities: IEntityMap): IConnection[] { + const typePredicate = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; + + // building block 2: every lc:Connection entity is taken from the page and processed + return Object.values(entities) + .filter((entity: IEntity) => + entity[typePredicate] && entity[typePredicate] === "http://semweb.mmlab.be/ns/linkedconnections#Connection", + ) as IConnection[]; + } + + private transformPredicate(triple: Triple): Triple { + return Rdf.transformPredicate({ + "http://semweb.mmlab.be/ns/linkedconnections#departureTime": "departureTime", + "http://semweb.mmlab.be/ns/linkedconnections#departureDelay": "departureDelay", + "http://semweb.mmlab.be/ns/linkedconnections#arrivalDelay": "arrivalDelay", + "http://semweb.mmlab.be/ns/linkedconnections#arrivalTime": "arrivalTime", + "http://semweb.mmlab.be/ns/linkedconnections#departureStop": "departureStop", + "http://semweb.mmlab.be/ns/linkedconnections#arrivalStop": "arrivalStop", + "http://semweb.mmlab.be/ns/linkedconnections#nextConnection": "nextConnection", + + "http://vocab.gtfs.org/terms#route": "gtfs:route", + "http://vocab.gtfs.org/terms#trip": "gtfs:trip", + "http://vocab.gtfs.org/terms#dropOffType": "gtfs:dropOffType", + "http://vocab.gtfs.org/terms#pickupType": "gtfs:pickupType", + "http://vocab.gtfs.org/terms#headsign": "gtfs:headsign", + }, triple); + } + + private transformObject(triple: Triple): Triple { + + if (triple.predicate.value === "gtfs:dropOffType") { + return Rdf.transformObject({ + "http://vocab.gtfs.org/terms#Regular": DropOffType.Regular, + "http://vocab.gtfs.org/terms#NotAvailable": DropOffType.NotAvailable, + "http://vocab.gtfs.org/terms#MustPhone": DropOffType.MustPhone, + "http://vocab.gtfs.org/terms#MustCoordinateWithDriver": DropOffType.MustCoordinateWithDriver, + }, triple); + } + + if (triple.predicate.value === "gtfs:pickupType") { + return Rdf.transformObject({ + "http://vocab.gtfs.org/terms#Regular": PickupType.Regular, + "http://vocab.gtfs.org/terms#NotAvailable": PickupType.NotAvailable, + "http://vocab.gtfs.org/terms#MustPhone": PickupType.MustPhone, + "http://vocab.gtfs.org/terms#MustCoordinateWithDriver": PickupType.MustCoordinateWithDriver, + }, triple); + } + + return triple; + } + + private getEntities(triples: Triple[]): IEntityMap { + + return triples.reduce((entities: IEntityMap, triple: Triple) => { + triple = this.transformObject(this.transformPredicate(triple)); + + const { subject: { value: subject }, predicate: { value: predicate }, object: { value: object } } = triple; + let newObject; + + if (triple.predicate.value === "departureTime" || triple.predicate.value === "arrivalTime") { + newObject = new Date(triple.object.value); + } + + if (triple.predicate.value === "departureDelay" || triple.predicate.value === "arrivalDelay") { + newObject = Units.fromSeconds(parseInt(triple.object.value, 10)); + } + + if (!entities[subject]) { + entities[subject] = { + id: subject, + }; + } + + // nextConnection should be an array + // todo: test once nextConnection becomes available + if (predicate === "nextConnection") { + entities[subject][predicate] = entities[subject][predicate] || []; + entities[subject][predicate].push(object); + + } else { + entities[subject][predicate] = newObject || object; + } + + return entities; + }, {}); + } +} diff --git a/src/fetcher/connections/ld-fetch/HydraPageParser.ts b/src/fetcher/connections/ld-fetch/HydraPageParser.ts new file mode 100644 index 00000000..7a0adcf0 --- /dev/null +++ b/src/fetcher/connections/ld-fetch/HydraPageParser.ts @@ -0,0 +1,80 @@ +import { Triple } from "rdf-js"; +import UriTemplate from "uritemplate"; +import TravelMode from "../../../TravelMode"; +import Rdf from "../../../util/Rdf"; +import ConnectionsPageParser from "./ConnectionsPageParser"; +import IHydraPage from "./IHydraPage"; + +/** + * Searches the given array of triples for hydra meta data, like the search template and next/previous page iris + * Also allows getting the contained [[IHydraPage]], which holds an array of [[IConnection]]s + */ +export default class HydraPageParser { + private readonly triples: Triple[]; + private readonly documentIri: string; + + constructor(triples: Triple[]) { + this.triples = triples; + this.documentIri = this.getDocumentIri(); + } + + public getPage(index: number, travelMode: TravelMode): IHydraPage { + const connectionsParser = new ConnectionsPageParser(this.documentIri, this.triples); + const connections = connectionsParser.getConnections(travelMode); + + return { + index, + documentIri: this.documentIri, + connections, + }; + } + + public getSearchTemplate(): UriTemplate { + const searchTriple = this.triples.find( + Rdf.matchesTriple(this.documentIri, "http://www.w3.org/ns/hydra/core#search", null), + ); + + const templateTriple = this.triples.find( + Rdf.matchesTriple(searchTriple.object.value, "http://www.w3.org/ns/hydra/core#template", null), + ); + + const template = templateTriple.object.value; + return UriTemplate.parse(template); + } + + public getNextPageIri(): string { + const nextPageTriple: Triple = this.triples.find( + Rdf.matchesTriple(this.documentIri, "http://www.w3.org/ns/hydra/core#next", null), + ); + + if (nextPageTriple && nextPageTriple.object.value.substr(0, 4) === "http") { + return nextPageTriple.object.value; + } + } + + public getPreviousPageIri(): string { + const previousPageTriple: Triple = this.triples.find( + Rdf.matchesTriple(this.documentIri, "http://www.w3.org/ns/hydra/core#previous", null), + ); + + if (previousPageTriple && previousPageTriple.object.value.substr(0, 4) === "http") { + return previousPageTriple.object.value; + } + } + + private getDocumentIri(): string { + const typeTriple = this.triples.find( + Rdf.matchesTriple( + null, + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + "http://www.w3.org/ns/hydra/core#PartialCollectionView", + ), + ); + + if (!typeTriple) { + throw new Error("Hydra page doesn`t have type triple"); + } + + return typeTriple.subject.value; + } +} diff --git a/src/fetcher/connections/ld-fetch/IHydraPage.ts b/src/fetcher/connections/ld-fetch/IHydraPage.ts new file mode 100644 index 00000000..be94cad5 --- /dev/null +++ b/src/fetcher/connections/ld-fetch/IHydraPage.ts @@ -0,0 +1,9 @@ +import IConnection from "../IConnection"; + +export default interface IHydraPage { + index: number; + documentIri: string; + nextPageIri?: string; + previousPageIri?: string; + connections: IConnection[]; +} diff --git a/src/fetcher/connections/merge/ConnectionsFetcherMerge.ts b/src/fetcher/connections/merge/ConnectionsProviderMerge.ts similarity index 72% rename from src/fetcher/connections/merge/ConnectionsFetcherMerge.ts rename to src/fetcher/connections/merge/ConnectionsProviderMerge.ts index 2714cdde..ae8b53e1 100644 --- a/src/fetcher/connections/merge/ConnectionsFetcherMerge.ts +++ b/src/fetcher/connections/merge/ConnectionsProviderMerge.ts @@ -1,3 +1,4 @@ +import { AsyncIterator } from "asynciterator"; import { injectable, multiInject, tagged } from "inversify"; import TYPES from "../../../types"; import IConnection from "../IConnection"; @@ -6,7 +7,9 @@ import IConnectionsFetcherConfig from "../IConnectionsFetcherConfig"; import ConnectionsIteratorMerge from "./ConnectionsIteratorMerge"; @injectable() -export default class ConnectionsFetcherMerge implements IConnectionsFetcher { +export default class ConnectionsProviderMerge implements IConnectionsFetcher { + + public createIterator: () => AsyncIterator; private config: IConnectionsFetcherConfig; private connectionsFetchers: IConnectionsFetcher[]; @@ -17,12 +20,6 @@ export default class ConnectionsFetcherMerge implements IConnectionsFetcher { this.connectionsFetchers = connectionsFetchers; } - public [Symbol.asyncIterator](): AsyncIterator { - const iterators = this.connectionsFetchers.map((fetcher) => fetcher[Symbol.asyncIterator]()); - - return new ConnectionsIteratorMerge(iterators, this.config); - } - public setConfig(config: IConnectionsFetcherConfig): void { this.config = config; this.connectionsFetchers.forEach((fetcher) => { diff --git a/src/fetcher/connections/tests/ConnectionsFetcherNMBSTest.ts b/src/fetcher/connections/tests/ConnectionsFetcherNMBSTest.ts new file mode 100644 index 00000000..f512dc0f --- /dev/null +++ b/src/fetcher/connections/tests/ConnectionsFetcherNMBSTest.ts @@ -0,0 +1,31 @@ +import { ArrayIterator, AsyncIterator } from "asynciterator"; +import { injectable } from "inversify"; +import IConnection from "../IConnection"; +import IConnectionsFetcher from "../IConnectionsFetcher"; +import IConnectionsFetcherConfig from "../IConnectionsFetcherConfig"; + +@injectable() +export default class ConnectionsFetcherNMBSTest implements IConnectionsFetcher { + + private connections: Array> = []; + private config: IConnectionsFetcherConfig = {}; + + constructor(connections: Array>) { + this.connections = connections; + } + + public setConfig(config: IConnectionsFetcherConfig): void { + this.config = config; + } + + public createIterator(): AsyncIterator { + let array = this.connections + .map((r) => r.value); + + if (this.config.backward) { + array = array.reverse(); + } + + return new ArrayIterator(array); + } +} diff --git a/src/fetcher/connections/tests/data/ingelmunster-ghent.ts b/src/fetcher/connections/tests/data/ingelmunster-ghent.ts new file mode 100644 index 00000000..23ff7413 --- /dev/null +++ b/src/fetcher/connections/tests/data/ingelmunster-ghent.ts @@ -0,0 +1,246 @@ +import TravelMode from "../../../../TravelMode"; + +const connections = [ + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8891264/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008891314", + "arrivalTime": new Date("2018-11-06T10:30:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008891264", + "departureTime": new Date("2018-11-06T10:24:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8891314/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008892205", + "arrivalTime": new Date("2018-11-06T10:35:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008891314", + "departureTime": new Date("2018-11-06T10:31:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8892205/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008896800", + "arrivalTime": new Date("2018-11-06T10:43:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008892205", + "departureTime": new Date("2018-11-06T10:36:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8896800/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008896909", + "arrivalTime": new Date("2018-11-06T10:50:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008896800", + "departureTime": new Date("2018-11-06T10:44:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8896909/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008896925", + "arrivalTime": new Date("2018-11-06T10:56:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008896909", + "departureTime": new Date("2018-11-06T10:51:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8896925/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008896008", + "arrivalTime": new Date("2018-11-06T11:05:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008896925", + "departureTime": new Date("2018-11-06T10:56:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8896008/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008892601", + "arrivalTime": new Date("2018-11-06T11:29:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008896008", + "departureTime": new Date("2018-11-06T11:12:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8896008/20181106/IC412", + "arrivalStop": "http://irail.be/stations/NMBS/008896115", + "arrivalTime": new Date("2018-11-06T11:22:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008896008", + "departureTime": new Date("2018-11-06T11:17:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC412/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8896115/20181106/IC412", + "arrivalStop": "http://irail.be/stations/NMBS/008896149", + "arrivalTime": new Date("2018-11-06T11:29:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008896115", + "departureTime": new Date("2018-11-06T11:23:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC412/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8896149/20181106/IC412", + "arrivalStop": "http://irail.be/stations/NMBS/008892106", + "arrivalTime": new Date("2018-11-06T11:37:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008896149", + "departureTime": new Date("2018-11-06T11:30:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC412/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8892601/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008895208", + "arrivalTime": new Date("2018-11-06T11:44:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008892601", + "departureTime": new Date("2018-11-06T11:32:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8892106/20181106/IC412", + "arrivalStop": "http://irail.be/stations/NMBS/008892080", + "arrivalTime": new Date("2018-11-06T11:43:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008892106", + "departureTime": new Date("2018-11-06T11:38:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC412/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8892080/20181106/IC412", + "arrivalStop": "http://irail.be/stations/NMBS/008892007", + "arrivalTime": new Date("2018-11-06T11:51:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008892080", + "departureTime": new Date("2018-11-06T11:44:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC412/20181106", + }, + done: false, + }, + { + value: + { + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureDelay": 0, + "id": "http://irail.be/connections/8895208/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008895802", + "arrivalTime": new Date("2018-11-06T12:02:00.000Z"), + "departureStop": "http://irail.be/stations/NMBS/008895208", + "departureTime": new Date("2018-11-06T11:46:00.000Z"), + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "id": "http://irail.be/connections/8895802/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008814001", + "arrivalTime": new Date("2018-11-06T12:20:00.000Z"), + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureStop": "http://irail.be/stations/NMBS/008895802", + "departureTime": new Date("2018-11-06T12:05:00.000Z"), + "departureDelay": 0, + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, + { + value: + { + "id": "http://irail.be/connections/8814001/20181106/IC2310", + "arrivalStop": "http://irail.be/stations/NMBS/008813003", + "arrivalTime": new Date("2018-11-06T12:26:00.000Z"), + "arrivalDelay": 0, + "travelMode": TravelMode.Train, + "departureStop": "http://irail.be/stations/NMBS/008814001", + "departureTime": new Date("2018-11-06T12:23:00.000Z"), + "departureDelay": 0, + "gtfs:trip": "http://irail.be/vehicle/IC2310/20181106", + }, + done: false, + }, +]; + +export default connections; diff --git a/src/fetcher/connections/tests/data/joining.ts b/src/fetcher/connections/tests/data/joining.ts new file mode 100644 index 00000000..99a31faa --- /dev/null +++ b/src/fetcher/connections/tests/data/joining.ts @@ -0,0 +1,51 @@ +import TravelMode from "../../../../TravelMode"; +import DropOffType from "../../DropOffType"; +import PickupType from "../../PickupType"; + +const connections = [ + { + value: { + "id": "2a", + "travelMode": TravelMode.Train, + "arrivalStop": "http://irail.be/stations/NMBS/008891702", // B + "departureStop": "http://irail.be/stations/NMBS/008892007", // C + "departureTime": new Date("2017-12-19T16:22:00.000Z"), + "arrivalTime": new Date("2017-12-19T16:30:00.000Z"), + "gtfs:trip": "A", + "gtfs:pickupType": PickupType.Regular, + "gtfs:dropOffType": DropOffType.Regular, + }, + done: false, + }, + { + value: { + "id": "2b", + "travelMode": TravelMode.Train, + "arrivalStop": "http://irail.be/stations/NMBS/008891702", // B + "departureStop": "http://irail.be/stations/NMBS/008812005", // D + "departureTime": new Date("2017-12-19T16:23:00.000Z"), + "arrivalTime": new Date("2017-12-19T16:34:00.000Z"), + "gtfs:trip": "B", + "nextConnection": ["1"], + "gtfs:pickupType": PickupType.Regular, + "gtfs:dropOffType": DropOffType.Regular, + }, + done: false, + }, + { + value: { + "id": "1", + "travelMode": TravelMode.Train, + "arrivalStop": "http://irail.be/stations/NMBS/008821006", // A + "departureStop": "http://irail.be/stations/NMBS/008891702", // B + "departureTime": new Date("2017-12-19T16:35:00.000Z"), + "arrivalTime": new Date("2017-12-19T16:50:00.000Z"), + "gtfs:trip": "A", + "gtfs:pickupType": PickupType.Regular, + "gtfs:dropOffType": DropOffType.Regular, + }, + done: false, + }, +]; + +export default connections; diff --git a/src/fetcher/connections/tests/data/splitting.ts b/src/fetcher/connections/tests/data/splitting.ts new file mode 100644 index 00000000..56fae16a --- /dev/null +++ b/src/fetcher/connections/tests/data/splitting.ts @@ -0,0 +1,51 @@ +import TravelMode from "../../../../TravelMode"; +import DropOffType from "../../DropOffType"; +import PickupType from "../../PickupType"; + +const connections = [ + { + value: { + "id": "1", + "travelMode": TravelMode.Train, + "departureStop": "http://irail.be/stations/NMBS/008821006", // A + "arrivalStop": "http://irail.be/stations/NMBS/008891702", // B + "departureTime": new Date("2017-12-19T15:50:00.000Z"), + "arrivalTime": new Date("2017-12-19T16:20:00.000Z"), + "gtfs:trip": "A", + "nextConnection": ["2b"], + "gtfs:pickupType": PickupType.Regular, + "gtfs:dropOffType": DropOffType.Regular, + }, + done: false, + }, + { + value: { + "id": "2a", + "travelMode": TravelMode.Train, + "departureStop": "http://irail.be/stations/NMBS/008891702", // B + "arrivalStop": "http://irail.be/stations/NMBS/008892007", // C + "departureTime": new Date("2017-12-19T16:22:00.000Z"), + "arrivalTime": new Date("2017-12-19T16:30:00.000Z"), + "gtfs:trip": "A", + "gtfs:pickupType": PickupType.Regular, + "gtfs:dropOffType": DropOffType.Regular, + }, + done: false, + }, + { + value: { + "id": "2b", + "travelMode": TravelMode.Train, + "departureStop": "http://irail.be/stations/NMBS/008891702", // B + "arrivalStop": "http://irail.be/stations/NMBS/008812005", // D + "departureTime": new Date("2017-12-19T16:23:00.000Z"), + "arrivalTime": new Date("2017-12-19T16:50:00.000Z"), + "gtfs:trip": "B", + "gtfs:pickupType": PickupType.Regular, + "gtfs:dropOffType": DropOffType.Regular, + }, + done: false, + }, +]; + +export default connections; diff --git a/src/fetcher/helpers.ts b/src/fetcher/helpers.ts deleted file mode 100644 index 7876a44a..00000000 --- a/src/fetcher/helpers.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Triple } from "rdf-js"; - -const matchesTriple = (subject: string, predicate: string, object: string) => (triple: Triple) => { - if (subject && triple.subject.value !== subject) { - return false; - } - - if (predicate && triple.predicate.value !== predicate) { - return false; - } - - if (object && triple.object.value !== object) { - return false; - } - - return true; -}; - -const transformPredicate = (transformMap: {[oldPredicate: string]: string}, triple: Triple) => { - if (triple.predicate.value in transformMap) { - triple.predicate.value = transformMap[triple.predicate.value]; - } - return triple; -}; - -const logTripleTable = (triples: Triple[]) => { - console.table(triples.map((triple: Triple) => ({ - subject: triple.subject.value, - predicate: triple.predicate.value, - object: triple.object.value, - }))); -}; - -export {matchesTriple, transformPredicate, logTripleTable}; diff --git a/src/fetcher/stops/IStop.ts b/src/fetcher/stops/IStop.ts index 7166d4a3..b8adbf19 100644 --- a/src/fetcher/stops/IStop.ts +++ b/src/fetcher/stops/IStop.ts @@ -1,5 +1,10 @@ +/** + * Interface for a Stop. This describes an actual physical stop, e.g. a train or a bus stop + * @property id An identifier for the stop that gets used in IConnections + * @property name Display name of the stop + */ export default interface IStop { - "@id": string; + id: string; name: string; longitude: number; latitude: number; diff --git a/src/fetcher/stops/IStopsFetcher.ts b/src/fetcher/stops/IStopsFetcher.ts index f8ac2fe1..d2c9d3a1 100644 --- a/src/fetcher/stops/IStopsFetcher.ts +++ b/src/fetcher/stops/IStopsFetcher.ts @@ -1,6 +1,10 @@ -import IStop from "./IStop"; +import IStopsProvider from "./IStopsProvider"; -export default interface IStopsFetcher { +/** + * Represents one data source of stops, e.g. De Lijn or NMBS + * Has a prefix for potential use by a [[IStopsProvider]] + * Extends [[IStopsProvider]] because it should implement the same methods + */ +export default interface IStopsFetcher extends IStopsProvider { prefix: string; - getStopById: (stopId: string | string[]) => Promise; } diff --git a/src/fetcher/stops/IStopsProvider.ts b/src/fetcher/stops/IStopsProvider.ts new file mode 100644 index 00000000..95ef130f --- /dev/null +++ b/src/fetcher/stops/IStopsProvider.ts @@ -0,0 +1,12 @@ +import IStop from "./IStop"; + +/** + * Acts as transparent proxy to [[IStopsFetcher]] instances by choosing + * the right [[IStopsFetcher]] to pass the request to + * @method getStopById Returns the [[IStop]] for the given stopId + * @method getAllStops Returns concatenated array of [[IStop]]s from all [[IStopsFetcher]]s it mediates + */ +export default interface IStopsProvider { + getStopById: (stopId: string) => Promise; + getAllStops: () => Promise; +} diff --git a/src/fetcher/stops/StopsFetcherDeLijn.test.ts b/src/fetcher/stops/StopsFetcherDeLijn.test.ts deleted file mode 100644 index a0a5486d..00000000 --- a/src/fetcher/stops/StopsFetcherDeLijn.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import "jest"; -import IStop from "./IStop"; -import IStopsFetcher from "./IStopsFetcher"; -import StopsFetcherDeLijn from "./StopsFetcherDeLijn"; - -const fetcher: IStopsFetcher = new StopsFetcherDeLijn(); - -test("[StopsFetcherDeLijn] first stop", async () => { - const stop: IStop = await fetcher.getStopById("https://data.delijn.be/stops/590009"); - - console.log(stop); - - expect(stop).toBeDefined(); - expect(stop.name).toEqual("De Vierweg"); -}); - -test("[StopsFetcherDeLijn] second stop", async () => { - const stop: IStop = await fetcher.getStopById("https://data.delijn.be/stops/219025"); - - console.log(stop); - - expect(stop).toBeDefined(); - expect(stop.name).toEqual("Brandweer"); -}); diff --git a/src/fetcher/stops/StopsFetcherDeLijn.ts b/src/fetcher/stops/StopsFetcherDeLijn.ts deleted file mode 100644 index 932f69fb..00000000 --- a/src/fetcher/stops/StopsFetcherDeLijn.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { injectable } from "inversify"; -import IStopsFetcher from "./IStopsFetcher"; -import StopsFetcherLDFetch from "./StopsFetcherLDFetch"; - -const STOPS_URLS = [ - "http://openplanner.ilabt.imec.be/delijn/Antwerpen/stops", - "http://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/stops", - "http://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/stops", - "http://openplanner.ilabt.imec.be/delijn/Vlaams-Brabant/stops", - "http://openplanner.ilabt.imec.be/delijn/Limburg/stops", -]; - -@injectable() -export default class StopsFetcherDeLijn extends StopsFetcherLDFetch implements IStopsFetcher { - - constructor() { - super("https://data.delijn.be/stops/", STOPS_URLS); - } - -} diff --git a/src/fetcher/stops/StopsFetcherNMBS.test.ts b/src/fetcher/stops/StopsFetcherNMBS.test.ts deleted file mode 100644 index c889cf63..00000000 --- a/src/fetcher/stops/StopsFetcherNMBS.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import "jest"; -import IStop from "./IStop"; -import IStopsFetcher from "./IStopsFetcher"; -import StopsFetcherNMBS from "./StopsFetcherNMBS"; - -test("[StopsFetcherNMBS]", async () => { - const fetcher: IStopsFetcher = new StopsFetcherNMBS(); - const stop: IStop = await fetcher.getStopById("http://irail.be/stations/NMBS/008896008"); - - console.log(stop); - - expect(stop).toBeDefined(); - expect(stop.name).toEqual("Kortrijk"); -}); diff --git a/src/fetcher/stops/StopsFetcherNMBS.ts b/src/fetcher/stops/StopsFetcherNMBS.ts deleted file mode 100644 index 7f7a21f6..00000000 --- a/src/fetcher/stops/StopsFetcherNMBS.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { injectable } from "inversify"; -import StopsFetcherLDFetch from "./StopsFetcherLDFetch"; - -const IRAIL_STATIONS_URL = "https://irail.be/stations/NMBS"; - -@injectable() -export default class StopsFetcherNMBS extends StopsFetcherLDFetch { - - constructor() { - super("http://irail.be/stations/NMBS/", [IRAIL_STATIONS_URL]); - } - -} diff --git a/src/fetcher/stops/StopsFetcherNMBSJSON.ts b/src/fetcher/stops/StopsFetcherNMBSJSON.ts deleted file mode 100644 index ba6a6dce..00000000 --- a/src/fetcher/stops/StopsFetcherNMBSJSON.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { injectable } from "inversify"; -import IStop from "./IStop"; -import IStopsFetcher from "./IStopsFetcher"; - -const IRAIL_STATIONS_URL = "https://api.irail.be/stations/?format=json"; - -interface IStopMap { - [stopId: string]: IStop; -} - -@injectable() -export default class StopsFetcherNMBSJSON implements IStopsFetcher { - - public prefix = "http://irail.be/stations/NMBS/"; - - private loadPromise: Promise; - private stops: IStopMap; - - constructor() { - this.loadStops(); - } - - public async getStopById(stopId: string): Promise { - if (this.loadPromise) { - await this.loadPromise; - } - - return this.stops[stopId]; - } - - private loadStops() { - this.loadPromise = fetch(IRAIL_STATIONS_URL) - .then((response: Response) => response.json()) - .then(({station: stations}) => { - - this.stops = stations.reduce((accu: IStopMap, stop) => { - stop.latitude = parseFloat(stop.locationY); - stop.longitude = parseFloat(stop.locationX); - accu[stop["@id"]] = stop as IStop; - return accu; - }, {}); - - this.loadPromise = null; - }); - } -} diff --git a/src/fetcher/stops/StopsProviderDefault.ts b/src/fetcher/stops/StopsProviderDefault.ts new file mode 100644 index 00000000..4398c39d --- /dev/null +++ b/src/fetcher/stops/StopsProviderDefault.ts @@ -0,0 +1,46 @@ +import { inject, injectable } from "inversify"; +import Catalog from "../../Catalog"; +import TYPES, { StopsFetcherFactory } from "../../types"; +import IStop from "./IStop"; +import IStopsFetcher from "./IStopsFetcher"; +import IStopsProvider from "./IStopsProvider"; + +@injectable() +export default class StopsProviderDefault implements IStopsProvider { + + private readonly stopsFetchers: IStopsFetcher[]; + + constructor( + @inject(TYPES.StopsFetcherFactory) stopsFetcherFactory: StopsFetcherFactory, + @inject(TYPES.Catalog) catalog: Catalog, + ) { + this.stopsFetchers = []; + + for (const {prefix, accessUrl} of catalog.stopsFetcherConfigs) { + this.stopsFetchers.push(stopsFetcherFactory(prefix, accessUrl)); + } + } + + public async getStopById(stopId: string): Promise { + const fetcher = this.determineStopFetcher(stopId); + + if (fetcher) { + return fetcher.getStopById(stopId); + } + } + + public async getAllStops(): Promise { + return Promise.all(this.stopsFetchers + .map((stopsFetcher: IStopsFetcher) => stopsFetcher.getAllStops()), + ).then((results: IStop[][]) => [].concat(...results)); + } + + private determineStopFetcher(stopId: string): IStopsFetcher { + if (!this.stopsFetchers || !this.stopsFetchers.length) { + return null; + } + + return this.stopsFetchers + .find((fetcher) => stopId.indexOf(fetcher.prefix) === 0); + } +} diff --git a/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.test.ts b/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.test.ts new file mode 100644 index 00000000..da6b6fda --- /dev/null +++ b/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.test.ts @@ -0,0 +1,52 @@ +import "jest"; +import LDFetch from "ldfetch"; +import IStop from "../IStop"; +import StopsFetcherLDFetch from "./StopsFetcherLDFetch"; + +const DE_LIJN_STOPS_URLS = [ + "http://openplanner.ilabt.imec.be/delijn/Antwerpen/stops", + "http://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/stops", + "http://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/stops", + "http://openplanner.ilabt.imec.be/delijn/Vlaams-Brabant/stops", + "http://openplanner.ilabt.imec.be/delijn/Limburg/stops", +]; + +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + +const deLijnFetcher = new StopsFetcherLDFetch(ldFetch); +deLijnFetcher.setPrefix("https://data.delijn.be/stops/"); +deLijnFetcher.setAccessUrl(DE_LIJN_STOPS_URLS[2]); + +const nmbsFetcher = new StopsFetcherLDFetch(ldFetch); +nmbsFetcher.setPrefix("http://irail.be/stations/NMBS/"); +nmbsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); + +test("[StopsFetcherLDFetch] De Lijn first stop", async () => { + jest.setTimeout(15000); + + const stop: IStop = await deLijnFetcher.getStopById("https://data.delijn.be/stops/590009"); + + expect(stop).toBeDefined(); + expect(stop.name).toEqual("De Vierweg"); +}); + +// test("[StopsFetcherLDFetch] De Lijn second stop", async () => { +// const stop: IStop = await deLijnFetcher.getStopById("https://data.delijn.be/stops/219025"); +// +// expect(stop).toBeDefined(); +// expect(stop.name).toEqual("Brandweer"); +// }); + +test("[StopsFetcherLDFetch] De Lijn second stop", async () => { + const stop: IStop = await deLijnFetcher.getStopById("https://data.delijn.be/stops/500050"); + + expect(stop).toBeDefined(); + expect(stop.name).toEqual("Station perron 10"); +}); + +test("[StopsFetcherLDFetch] NMBS", async () => { + const stop: IStop = await nmbsFetcher.getStopById("http://irail.be/stations/NMBS/008896008"); + + expect(stop).toBeDefined(); + expect(stop.name).toEqual("Kortrijk"); +}); diff --git a/src/fetcher/stops/StopsFetcherLDFetch.ts b/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.ts similarity index 59% rename from src/fetcher/stops/StopsFetcherLDFetch.ts rename to src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.ts index bd727c95..d47fdb63 100644 --- a/src/fetcher/stops/StopsFetcherLDFetch.ts +++ b/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.ts @@ -1,9 +1,10 @@ -import { injectable, unmanaged } from "inversify"; +import { inject, injectable } from "inversify"; import LDFetch from "ldfetch"; import { Triple } from "rdf-js"; -import { transformPredicate } from "../helpers"; -import IStop from "./IStop"; -import IStopsFetcher from "./IStopsFetcher"; +import TYPES from "../../../types"; +import Rdf from "../../../util/Rdf"; +import IStop from "../IStop"; +import IStopsFetcher from "../IStopsFetcher"; interface IPartialStopMap { [stopId: string]: Partial; @@ -16,48 +17,67 @@ interface IStopMap { @injectable() export default class StopsFetcherLDFetch implements IStopsFetcher { - public readonly prefix: string; - private readonly sources: string[]; + public prefix: string; + private accessUrl: string; private ldFetch: LDFetch; private loadPromise: Promise; private stops: IStopMap; - constructor(@unmanaged() prefix: string, @unmanaged() sources: string[]) { - this.prefix = prefix; - this.sources = sources; - this.ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + constructor( + @inject(TYPES.LDFetch) ldFetch: LDFetch, + ) { + this.ldFetch = ldFetch; this.loadStops(); } + public setPrefix(prefix: string) { + this.prefix = prefix; + } + + public setAccessUrl(accessUrl: string) { + this.accessUrl = accessUrl; + } + public async getStopById(stopId: string): Promise { - if (this.loadPromise) { - await this.loadPromise; - } + await this.ensureStopsLoaded(); return this.stops[stopId]; } - private loadStops() { - if (this.sources) { + public async getAllStops(): Promise { + await this.ensureStopsLoaded(); - this.loadPromise = Promise - .all(this.sources.map((url) => this.ldFetch.get(url))) - .then((responses) => { - // logTripleTable(response.triples); + return Object.values(this.stops); + } + + private async ensureStopsLoaded() { + if (!this.loadPromise && !this.stops) { + this.loadStops(); + } - this.stops = responses.reduce((stops, response) => { - Object.assign(stops, this.parseTriples(response.triples)); - return stops; - }, {}); + if (this.loadPromise) { + await this.loadPromise; + } + } + + private loadStops() { + if (this.accessUrl) { + this.loadPromise = this.ldFetch + .get(this.accessUrl) + .then((response) => { + this.stops = this.parseTriples(response.triples); this.loadPromise = null; + }) + .catch((reason) => { + console.log(reason); }); } } private transformPredicate(triple: Triple): Triple { - return transformPredicate({ + return Rdf.transformPredicate({ "http://xmlns.com/foaf/0.1/name": "name", "http://www.w3.org/2003/01/geo/wgs84_pos#lat": "latitude", "http://www.w3.org/2003/01/geo/wgs84_pos#long": "longitude", @@ -72,7 +92,7 @@ export default class StopsFetcherLDFetch implements IStopsFetcher { if (!(subject in stopMap)) { stopMap[subject] = { - "@id": subject, + id: subject, }; } diff --git a/src/index.ts b/src/index.ts index 0feae7cb..99ba7489 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,24 +2,4 @@ import "isomorphic-fetch"; import "reflect-metadata"; import Planner from "./Planner"; -const planner = new Planner(); - -(async () => { - - const roadOnlyResult = await planner.query({ - roadOnly: true, - from: "http://irail.be/stations/NMBS/008896008", // Kortrijk - to: "http://irail.be/stations/NMBS/008892007", // Ghent-Sint-Pieters - }); - - console.log(JSON.stringify(roadOnlyResult, null, " ")); - - const publicTransportResult = await planner.query({ - publicTransportOnly: true, - from: "http://irail.be/stations/NMBS/008896925", // Ingelmunster - to: "http://irail.be/stations/NMBS/008892007", // Ghent-Sint-Pieters - }); - - console.log(JSON.stringify(publicTransportResult, null, " ")); - -})(); +export default Planner; diff --git a/src/interfaces/ILocation.ts b/src/interfaces/ILocation.ts index 575a4204..c0a5681d 100644 --- a/src/interfaces/ILocation.ts +++ b/src/interfaces/ILocation.ts @@ -1,6 +1,6 @@ export default interface ILocation { id?: string; - time?: Date; + name?: string; longitude?: number; latitude?: number; } diff --git a/src/interfaces/IPath.ts b/src/interfaces/IPath.ts index 40dd239e..efbfce40 100644 --- a/src/interfaces/IPath.ts +++ b/src/interfaces/IPath.ts @@ -1,8 +1,5 @@ import IStep from "./IStep"; export default interface IPath { - departureTime?: Date; - arrivalTime?: Date; - transfers?: number; steps: IStep[]; } diff --git a/src/interfaces/IProbabilisticValue.ts b/src/interfaces/IProbabilisticValue.ts index 0ec4932d..c1d2dc75 100644 --- a/src/interfaces/IProbabilisticValue.ts +++ b/src/interfaces/IProbabilisticValue.ts @@ -1,7 +1,7 @@ -export default interface IProbabilisticValue { - median?: number; - average?: number; - minimum?: number; - maximum?: number; - percentiles?: {[percentile: string]: number}; +export default interface IProbabilisticValue { + median?: T; + average?: T; + minimum?: T; + maximum?: T; + percentiles?: {[percentile: string]: T}; } diff --git a/src/interfaces/IQuery.ts b/src/interfaces/IQuery.ts index a0fc5665..3041e945 100644 --- a/src/interfaces/IQuery.ts +++ b/src/interfaces/IQuery.ts @@ -1,4 +1,5 @@ import ILocation from "./ILocation"; +import { DurationMs, SpeedkmH } from "./units"; export default interface IQuery { from?: string | string[] | ILocation | ILocation[]; @@ -7,7 +8,9 @@ export default interface IQuery { maximumArrivalTime?: Date; roadOnly?: boolean; publicTransportOnly?: boolean; - walkingSpeed?: number; - minimumWalkingSpeed?: number; - maximumWalkingSpeed?: number; + walkingSpeed?: SpeedkmH; + minimumWalkingSpeed?: SpeedkmH; + maximumWalkingSpeed?: SpeedkmH; + maximumTransferDuration?: DurationMs; + maximumTransfers?: number; } diff --git a/src/interfaces/IQueryResult.ts b/src/interfaces/IQueryResult.ts deleted file mode 100644 index 5f1af3c5..00000000 --- a/src/interfaces/IQueryResult.ts +++ /dev/null @@ -1,6 +0,0 @@ -import IPath from "./IPath"; - -export default interface IQueryResult { - paths?: IPath[]; - error?: Error; -} diff --git a/src/interfaces/IStep.ts b/src/interfaces/IStep.ts index 3f3b7aea..bf475b41 100644 --- a/src/interfaces/IStep.ts +++ b/src/interfaces/IStep.ts @@ -1,9 +1,16 @@ +import TravelMode from "../TravelMode"; import ILocation from "./ILocation"; import IProbabilisticValue from "./IProbabilisticValue"; +import { DistanceM, DurationMs } from "./units"; export default interface IStep { startLocation: ILocation; stopLocation: ILocation; - duration: IProbabilisticValue; - distance?: number; + travelMode: TravelMode; + startTime?: Date; + stopTime?: Date; + duration: IProbabilisticValue; + distance?: DistanceM; + enterConnectionId?: string; + exitConnectionId?: string; } diff --git a/src/interfaces/units.ts b/src/interfaces/units.ts new file mode 100644 index 00000000..23f52d27 --- /dev/null +++ b/src/interfaces/units.ts @@ -0,0 +1,6 @@ +// duration ms +export type DurationMs = number; +// distance in m +export type DistanceM = number; +// speed in km/h +export type SpeedkmH = number; diff --git a/src/inversify.config.ts b/src/inversify.config.ts index fffd8096..ad05a770 100644 --- a/src/inversify.config.ts +++ b/src/inversify.config.ts @@ -1,38 +1,106 @@ -import { Container } from "inversify"; +import { Container, interfaces } from "inversify"; +import LDFetch from "ldfetch"; +import Catalog from "./Catalog"; import Context from "./Context"; +import ConnectionsProviderPassthrough from "./fetcher/connections/ConnectionsProviderPassthrough"; import IConnectionsFetcher from "./fetcher/connections/IConnectionsFetcher"; -import ConnectionsFetcherDeLijn from "./fetcher/connections/ld-fetch/ConnectionsFetcherDeLijn"; -import ConnectionsFetcherNMBS from "./fetcher/connections/ld-fetch/ConnectionsFetcherNMBS"; -import ConnectionsFetcherMerge from "./fetcher/connections/merge/ConnectionsFetcherMerge"; +import IConnectionsProvider from "./fetcher/connections/IConnectionsProvider"; +import ConnectionsFetcherLazy from "./fetcher/connections/ld-fetch/ConnectionsFetcherLazy"; import IStopsFetcher from "./fetcher/stops/IStopsFetcher"; -import StopsFetcherNMBS from "./fetcher/stops/StopsFetcherNMBS"; +import IStopsProvider from "./fetcher/stops/IStopsProvider"; +import StopsFetcherLDFetch from "./fetcher/stops/ld-fetch/StopsFetcherLDFetch"; +import StopsProviderDefault from "./fetcher/stops/StopsProviderDefault"; +import IJourneyExtractor from "./planner/public-transport/IJourneyExtractor"; import IPublicTransportPlanner from "./planner/public-transport/IPublicTransportPlanner"; +import JourneyExtractionPhase from "./planner/public-transport/JourneyExtractionPhase"; +import JourneyExtractorDefault from "./planner/public-transport/JourneyExtractorDefault"; import PublicTransportPlannerCSAProfile from "./planner/public-transport/PublicTransportPlannerCSAProfile"; import IRoadPlanner from "./planner/road/IRoadPlanner"; import RoadPlannerBirdsEye from "./planner/road/RoadPlannerBirdsEye"; +import IReachableStopsFinder from "./planner/stops/IReachableStopsFinder"; +import ReachableStopsFinderBirdsEyeCached from "./planner/stops/ReachableStopsFinderBirdsEyeCached"; +import ReachableStopsSearchPhase from "./planner/stops/ReachableStopsSearchPhase"; +import QueryRunnerExponential from "./query-runner/exponential/QueryRunnerExponential"; import ILocationResolver from "./query-runner/ILocationResolver"; import IQueryRunner from "./query-runner/IQueryRunner"; import LocationResolverDefault from "./query-runner/LocationResolverDefault"; -import QueryRunnerDefault from "./query-runner/QueryRunnerDefault"; +import TravelMode from "./TravelMode"; import TYPES from "./types"; const container = new Container(); container.bind(TYPES.Context).to(Context).inSingletonScope(); -container.bind(TYPES.QueryRunner).to(QueryRunnerDefault); +container.bind(TYPES.QueryRunner).to(QueryRunnerExponential); container.bind(TYPES.LocationResolver).to(LocationResolverDefault); -container.bind(TYPES.PublicTransportPlanner).to(PublicTransportPlannerCSAProfile); -container.bind(TYPES.RoadPlanner).to(RoadPlannerBirdsEye); +container.bind(TYPES.PublicTransportPlanner) + .to(PublicTransportPlannerCSAProfile); -container.bind(TYPES.ConnectionsFetcher).to(ConnectionsFetcherNMBS); +container.bind(TYPES.JourneyExtractor) + .to(JourneyExtractorDefault); +container.bind(TYPES.RoadPlanner) + .to(RoadPlannerBirdsEye).whenTargetTagged("phase", JourneyExtractionPhase.Initial); +container.bind(TYPES.RoadPlanner) + .to(RoadPlannerBirdsEye).whenTargetTagged("phase", JourneyExtractionPhase.Transfer); +container.bind(TYPES.RoadPlanner) + .to(RoadPlannerBirdsEye).whenTargetTagged("phase", JourneyExtractionPhase.Final); -/*container.bind(TYPES.ConnectionsFetcher) - .to(ConnectionsFetcherNMBS).whenTargetTagged("type", "source"); -container.bind(TYPES.ConnectionsFetcher) - .to(ConnectionsFetcherDeLijn).whenTargetTagged("type", "source"); -container.bind(TYPES.ConnectionsFetcher) - .to(ConnectionsFetcherMerge).whenTargetTagged("type", "merge");*/ +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderBirdsEyeCached).whenTargetTagged("phase", ReachableStopsSearchPhase.Initial); +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderBirdsEyeCached).whenTargetTagged("phase", ReachableStopsSearchPhase.Transfer); +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderBirdsEyeCached).whenTargetTagged("phase", ReachableStopsSearchPhase.Final); -container.bind(TYPES.StopsFetcher).to(StopsFetcherNMBS); +container.bind(TYPES.ConnectionsProvider).to(ConnectionsProviderPassthrough).inSingletonScope(); +container.bind(TYPES.ConnectionsFetcher).to(ConnectionsFetcherLazy); +container.bind>(TYPES.ConnectionsFetcherFactory) + .toFactory( + (context: interfaces.Context) => + (accessUrl: string, travelMode: TravelMode) => { + const fetcher = context.container.get(TYPES.ConnectionsFetcher); + + fetcher.setAccessUrl(accessUrl); + fetcher.setTravelMode(travelMode); + + return fetcher; + }, + ); + +container.bind(TYPES.StopsProvider).to(StopsProviderDefault).inSingletonScope(); +container.bind(TYPES.StopsFetcher).to(StopsFetcherLDFetch); +container.bind>(TYPES.StopsFetcherFactory) + .toFactory( + (context: interfaces.Context) => + (prefix: string, accessUrl: string) => { + const fetcher = context.container.get(TYPES.StopsFetcher); + + fetcher.setPrefix(prefix); + fetcher.setAccessUrl(accessUrl); + + return fetcher; + }, + ); + +// Init catalog +const catalog = new Catalog(); +catalog.addStopsFetcher("http://irail.be/stations/NMBS/", "https://irail.be/stations/NMBS"); +catalog.addConnectionsFetcher("https://graph.irail.be/sncb/connections", TravelMode.Train); + +container.bind(TYPES.Catalog).toConstantValue(catalog); + +// Init LDFetch +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); +const httpStartTimes = {}; + +ldFetch.on("request", (url) => httpStartTimes[url] = new Date()); + +ldFetch.on("redirect", (obj) => httpStartTimes[obj.to] = httpStartTimes[obj.from]); + +ldFetch.on("response", (url) => { + const difference = (new Date()).getTime() - httpStartTimes[url].getTime(); + console.log(`HTTP GET - ${url} (${difference}ms)`); +}); + +container.bind(TYPES.LDFetch).toConstantValue(ldFetch); export default container; diff --git a/src/planner/IJourney.ts b/src/planner/IJourney.ts deleted file mode 100644 index 9a43fab4..00000000 --- a/src/planner/IJourney.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default interface IJourney { - distance: number; -} diff --git a/src/planner/IPlanner.ts b/src/planner/IPlanner.ts index 3a8aa692..28a85a84 100644 --- a/src/planner/IPlanner.ts +++ b/src/planner/IPlanner.ts @@ -1,6 +1,7 @@ +import { AsyncIterator } from "asynciterator"; import IPath from "../interfaces/IPath"; import IResolvedQuery from "../query-runner/IResolvedQuery"; export default interface IPlanner { - plan: (query: IResolvedQuery) => Promise; + plan: (query: IResolvedQuery) => Promise>; } diff --git a/src/planner/Path.ts b/src/planner/Path.ts new file mode 100644 index 00000000..ac79d24c --- /dev/null +++ b/src/planner/Path.ts @@ -0,0 +1,35 @@ +import IPath from "../interfaces/IPath"; +import IStep from "../interfaces/IStep"; +import Step from "./Step"; + +export default class Path implements IPath { + + public static create(): Path { + return new Path( + [], + ); + } + + public steps: IStep[]; + + constructor(steps: IStep[]) { + this.steps = steps; + } + + public addStep(step: IStep): void { + this.steps.push(step); + } + + public equals(path: IPath): boolean { + + if (this.steps.length !== path.steps.length) { + return false; + } + + return this.steps.every((step, stepIndex) => { + const otherStep = path.steps[stepIndex]; + + return Step.compareEquals(step, otherStep); + }); + } +} diff --git a/src/planner/PlannerPhase.ts b/src/planner/PlannerPhase.ts new file mode 100644 index 00000000..f4b23ef5 --- /dev/null +++ b/src/planner/PlannerPhase.ts @@ -0,0 +1,6 @@ +import JourneyExtractionPhase from "./public-transport/JourneyExtractionPhase"; +import ReachableStopsSearchPhase from "./stops/ReachableStopsSearchPhase"; + +type PlannerPhase = JourneyExtractionPhase | ReachableStopsSearchPhase; + +export default PlannerPhase; diff --git a/src/planner/Step.ts b/src/planner/Step.ts new file mode 100644 index 00000000..d9a9b770 --- /dev/null +++ b/src/planner/Step.ts @@ -0,0 +1,100 @@ +import IConnection from "../fetcher/connections/IConnection"; +import ILocation from "../interfaces/ILocation"; +import IProbabilisticValue from "../interfaces/IProbabilisticValue"; +import IStep from "../interfaces/IStep"; +import { DistanceM, DurationMs } from "../interfaces/units"; +import TravelMode from "../TravelMode"; + +export default class Step implements IStep { + + public static create( + startLocation: ILocation, + stopLocation: ILocation, + travelMode: TravelMode, + duration: IProbabilisticValue, + startTime?: Date, + stopTime?: Date, + distance?: DistanceM, + ): IStep { + return new Step( + startLocation, + stopLocation, + travelMode, + duration, + startTime, + stopTime, + distance, + ); + } + + public static createFromConnections(enterConnection: IConnection, exitConnection: IConnection): IStep { + return new Step( + {id: enterConnection.departureStop}, + {id: exitConnection.arrivalStop}, + enterConnection.travelMode, + { + minimum: ( + exitConnection.arrivalTime.getTime() - + enterConnection.departureTime.getTime() + ), + }, + enterConnection.departureTime, + exitConnection.arrivalTime, + undefined, + enterConnection.id, + exitConnection.id, + ); + } + + public static compareEquals(step: IStep, otherStep: IStep): boolean { + if (otherStep.travelMode !== step.travelMode) { + return false; + } + + if (otherStep.travelMode === TravelMode.Train || otherStep.travelMode === TravelMode.Bus) { + return otherStep.enterConnectionId === step.enterConnectionId && + otherStep.exitConnectionId === step.exitConnectionId; + } + + if (otherStep.travelMode === TravelMode.Walking) { + return Step.compareLocations(otherStep.startLocation, step.startLocation) && + Step.compareLocations(otherStep.stopLocation, step.stopLocation); + } + } + + private static compareLocations(a: ILocation, b: ILocation): boolean { + return a.id === b.id && a.longitude === b.longitude && a.latitude === b.latitude; + } + + public distance: DistanceM; + public duration: IProbabilisticValue; + public startLocation: ILocation; + public startTime: Date; + public stopLocation: ILocation; + public stopTime: Date; + public travelMode: TravelMode; + public enterConnectionId: string; + public exitConnectionId: string; + + constructor( + startLocation: ILocation, + stopLocation: ILocation, + travelMode: TravelMode, + duration: IProbabilisticValue, + startTime?: Date, + stopTime?: Date, + distance?: DistanceM, + enterConnectionId?: string, + exitConnectionId?: string, + ) { + this.distance = distance; + this.duration = duration; + this.travelMode = travelMode; + this.startLocation = startLocation; + this.startTime = startTime; + this.stopLocation = stopLocation; + this.stopTime = stopTime; + this.enterConnectionId = enterConnectionId; + this.exitConnectionId = exitConnectionId; + } +} diff --git a/src/planner/public-transport/CSA/JourneyExtractor.ts b/src/planner/public-transport/CSA/JourneyExtractor.ts deleted file mode 100644 index 9a145e0b..00000000 --- a/src/planner/public-transport/CSA/JourneyExtractor.ts +++ /dev/null @@ -1,150 +0,0 @@ -import IConnection from "../../../fetcher/connections/IConnection"; -import ILocation from "../../../interfaces/ILocation"; -import IPath from "../../../interfaces/IPath"; -import IStep from "../../../interfaces/IStep"; -import ILocationResolver from "../../../query-runner/ILocationResolver"; -import IRoadPlanner from "../../road/IRoadPlanner"; -import IProfilesByStop from "./dataStructure/IProfilesByStop"; -import Profile from "./dataStructure/Profile"; -import { filterInfinity } from "./utils"; - -export default class JourneyExtractor { - public readonly roadPlanner: IRoadPlanner; - public readonly locationResolver: ILocationResolver; - - private bestArrivalTime: number = Infinity; - - constructor(roadPlanner: IRoadPlanner, locationResolver: ILocationResolver) { - this.roadPlanner = roadPlanner; - this.locationResolver = locationResolver; - } - - public async extractJourneys( - profilesByStop: IProfilesByStop, - from: ILocation, - to: ILocation, - departureTime: Date, - ): Promise { - const profile: IProfilesByStop = filterInfinity(profilesByStop); - - const journeys = []; - for (const entry of profile[from.id]) { - if (entry.departureTime >= departureTime.getTime()) { - for (let transfers = 0; transfers < entry.arrivalTimes.length; transfers++) { - if (entry.arrivalTimes[transfers] < this.bestArrivalTime) { - const journey = await this.extractJourney(to, entry, transfers, profile); - journeys.push(journey); - } - } - } - } - return journeys; - } - - private async extractJourney( - target: ILocation, - entry: Profile, - transfers: number, - profile: IProfilesByStop, - ): Promise { - // Extract journey for amount of transfers - const journey: IPath = this.createJourney(entry, transfers); - this.bestArrivalTime = entry.arrivalTimes[transfers]; - - let currentEntry = entry; - let remainingTransfers = transfers; - - while (remainingTransfers >= 0) { - // Construct and push step - const enterConnection: IConnection = currentEntry.enterConnections[remainingTransfers]; - const exitConnection: IConnection = currentEntry.exitConnections[remainingTransfers]; - - const step: IStep = this.createStep(enterConnection, exitConnection); - journey.steps.push(step); - - remainingTransfers--; - if (remainingTransfers >= 0) { - const nextProfile = profile[step.stopLocation.id]; - - let i = nextProfile.length - 1; - let found = false; - - while (!found) { - const connection = nextProfile[i].enterConnections[remainingTransfers]; - - const from = await this.locationResolver.resolve({id: step.stopLocation.id }); - const to = await this.locationResolver.resolve({id: connection.departureStop}); - - const walkingResult = await this.roadPlanner.plan({ - from: [from], - to: [to], - minimumWalkingSpeed: 3, - maximumWalkingSpeed: 6, - }); - - if (walkingResult && walkingResult[0] && walkingResult[0].steps[0] && - connection.departureTime.getTime() >= step.stopLocation.time.getTime() + - walkingResult[0].steps[0].duration.average - ) { - found = true; - journey.steps.push(walkingResult[0].steps[0]); - currentEntry = nextProfile[i]; - } - i--; - } - } - } - - if (journey.steps[journey.steps.length - 1].stopLocation.id !== target.id) { - await this.addFinalFootpath(journey, target); - } - - return journey; - } - - private createJourney(entry: Profile, transfers: number): IPath { - return { - departureTime: new Date(entry.departureTime), - arrivalTime: new Date(entry.arrivalTimes[transfers]), - transfers, - steps: [], - }; - } - - private createStep(enterConnection: IConnection, exitConnection: IConnection): IStep { - return { - startLocation: { - id: enterConnection.departureStop, - time: exitConnection.departureTime, - }, - stopLocation: { - id: exitConnection.arrivalStop, - time: exitConnection.arrivalTime, - }, - duration: { - average: ( - exitConnection.arrivalTime.getTime() - - enterConnection.departureTime.getTime() - ), - }, - }; - } - - private async addFinalFootpath(journey: IPath, to: ILocation): Promise { - const lastStep = journey.steps[journey.steps.length - 1]; - - const fromLocation = await this.locationResolver.resolve({id: lastStep.stopLocation.id }); - const toLocation = await this.locationResolver.resolve(to); - - const walkingResult = await this.roadPlanner.plan({ - from: [fromLocation], - to: [toLocation], - minimumWalkingSpeed: 3, - maximumWalkingSpeed: 6, - }); - - if (walkingResult && walkingResult[0] && walkingResult[0].steps[0]) { - journey.steps.push(walkingResult[0].steps[0]); - } - } -} diff --git a/src/planner/public-transport/CSA/data-structure/IArrivalTimeByTransfers.ts b/src/planner/public-transport/CSA/data-structure/IArrivalTimeByTransfers.ts new file mode 100644 index 00000000..d9d8174f --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/IArrivalTimeByTransfers.ts @@ -0,0 +1,10 @@ +/** + * Stores an arrival time in milliseconds and the corresponding gtfs:trip + * for a maximum amount of transfers that can be made. + */ +export default interface IArrivalTimeByTransfers extends Array { + [amountOfTransfers: number]: { + arrivalTime: number, + "gtfs:trip"?: string, + }; +} diff --git a/src/planner/public-transport/CSA/data-structure/stops/IProfile.ts b/src/planner/public-transport/CSA/data-structure/stops/IProfile.ts new file mode 100644 index 00000000..2b8a8366 --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/stops/IProfile.ts @@ -0,0 +1,13 @@ +import ITransferProfile from "./ITransferProfile"; + +/** + * Interface for the CSA profile. + * + * @property departureTime Describes the departure time in milliseconds to the target. + * @property transferProfiles Stores an [[ITransferProfile]] for a maximum amount of transfers that can be made. + */ +export default interface IProfile { + departureTime: number; + + transferProfiles: ITransferProfile[]; +} diff --git a/src/planner/public-transport/CSA/data-structure/stops/IProfilesByStop.ts b/src/planner/public-transport/CSA/data-structure/stops/IProfilesByStop.ts new file mode 100644 index 00000000..33e5e825 --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/stops/IProfilesByStop.ts @@ -0,0 +1,8 @@ +import IProfile from "./Profile"; + +/** + * Stores multiple [[IProfile]]'s ordered by departure time for an [[IStop]]. + */ +export default interface IProfilesByStop { + [stop: string]: IProfile[]; +} diff --git a/src/planner/public-transport/CSA/data-structure/stops/ITransferProfile.ts b/src/planner/public-transport/CSA/data-structure/stops/ITransferProfile.ts new file mode 100644 index 00000000..e2fa68f2 --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/stops/ITransferProfile.ts @@ -0,0 +1,15 @@ +import IConnection from "../../../../../fetcher/connections/IConnection"; + +/** + * Interface for the CSA profile for a specific amount of transfers that can be made. + * + * @property arrivalTime Describes the arrival time in milliseconds. + * @property exitConnection Describes the [[IConnection]] that arrives at the target [[IStop]]. + * @property enterConnection Describes the [[IConnection]] that should be taken + * to arrive at the arrivalTime in the target [[IStop]]. + */ +export default interface ITransferProfile { + arrivalTime: number; + exitConnection: IConnection; + enterConnection: IConnection; +} diff --git a/src/planner/public-transport/CSA/data-structure/stops/Profile.ts b/src/planner/public-transport/CSA/data-structure/stops/Profile.ts new file mode 100644 index 00000000..de9805c8 --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/stops/Profile.ts @@ -0,0 +1,66 @@ +import IArrivalTimeByTransfers from "../IArrivalTimeByTransfers"; +import IProfile from "./IProfile"; +import ITransferProfile from "./ITransferProfile"; + +/** + * A factory that create's an [[IProfile]] based on the maximum amount of transfers and/or [[ITransferProfile]]s. + * + * @implements [[IProfile]] + */ +export default class Profile implements IProfile { + + public static create(amountOfTransfers: number): Profile { + return new Profile( + amountOfTransfers, + ); + } + + public static createFromTransfers( + departureTime: number, + transferProfiles?: ITransferProfile[], + ): Profile { + return new Profile( + transferProfiles.length, + departureTime, + transferProfiles, + ); + } + + public departureTime: number; + public transferProfiles: ITransferProfile[]; + + constructor( + amountOfTransfers: number, + departureTime?: number, + transferProfiles?: ITransferProfile[], + ) { + this.departureTime = departureTime || Infinity; + + if (transferProfiles) { + this.transferProfiles = transferProfiles; + } else { + this.transferProfiles = Array(amountOfTransfers + 1).fill({ + exitConnection: undefined, + enterConnection: undefined, + arrivalTime: Infinity, + }); + } + } + + public isDominated(arrivalTimeByTransfers: IArrivalTimeByTransfers): boolean { + return this.transferProfiles.reduce(( + memo: boolean, + transferProfile: ITransferProfile, + amountOfTransfers: number, + ) => + memo && transferProfile.arrivalTime <= arrivalTimeByTransfers[amountOfTransfers].arrivalTime + , true); + } + + public getArrivalTimeByTransfers(tripId?: string): IArrivalTimeByTransfers { + return this.transferProfiles.map((transfer: ITransferProfile) => ({ + "arrivalTime": transfer.arrivalTime, + "gtfs:trip": tripId, + })); + } +} diff --git a/src/planner/public-transport/CSA/data-structure/trips/EarliestArrivalByTransfers.ts b/src/planner/public-transport/CSA/data-structure/trips/EarliestArrivalByTransfers.ts new file mode 100644 index 00000000..3a101353 --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/trips/EarliestArrivalByTransfers.ts @@ -0,0 +1,45 @@ +import IConnection from "../../../../../fetcher/connections/IConnection"; +import IArrivalTimeByTransfers from "../IArrivalTimeByTransfers"; +import IEarliestArrival from "./IEarliestArrival"; +import IEarliestArrivalByTransfers from "./IEarliestArrivalByTransfers"; + +/** + * A factory that create's an [[IEarliestArrival]] for each amount of maximum transfers that can be made. + * + * @implements [[IEarliestArrivalByTransfers]] + */ +export default class EarliestArrivalByTransfers extends Array implements IEarliestArrivalByTransfers { + public static create(amountOfTransfers: number): EarliestArrivalByTransfers { + return new EarliestArrivalByTransfers(amountOfTransfers); + } + + public static createByConnection( + currentArrivalTimeByTransfers: EarliestArrivalByTransfers, + connection: IConnection, + arrivalTimeByTransfers: IArrivalTimeByTransfers, + ): EarliestArrivalByTransfers { + return currentArrivalTimeByTransfers.map((earliestArrival: IEarliestArrival, transfer: number) => { + if (arrivalTimeByTransfers[transfer].arrivalTime < earliestArrival.arrivalTime) { + return { + connection, + arrivalTime: arrivalTimeByTransfers[transfer].arrivalTime, + }; + } + + return earliestArrival; + }); + } + + [amountOfTransfers: number]: IEarliestArrival; + + constructor(maximumTransfers: number) { + super(); + + for (let amountOfTransfers = 0 ; amountOfTransfers < maximumTransfers + 1 ; amountOfTransfers++) { + this[amountOfTransfers] = { + arrivalTime: Infinity, + connection: undefined, + }; + } + } +} diff --git a/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrival.ts b/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrival.ts new file mode 100644 index 00000000..c97870b7 --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrival.ts @@ -0,0 +1,11 @@ +import IConnection from "../../../../../fetcher/connections/IConnection"; + +/** + * @property arrivalTime Describes the earliest arrival time in milliseconds to the target [[IStop]]. + * @property connection Describes the [[IConnection]] that should be taken to arrive + * at the arrivalTime in the target location. + */ +export default interface IEarliestArrival { + arrivalTime: number; + connection: IConnection; +} diff --git a/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrivalByTransfers.ts b/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrivalByTransfers.ts new file mode 100644 index 00000000..45a2eeba --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrivalByTransfers.ts @@ -0,0 +1,8 @@ +import IEarliestArrival from "./IEarliestArrival"; + +/** + * Stores the earliest arrival [[IEarliestArrival]] for a maximum amount of transfers. + */ +export default interface IEarliestArrivalByTransfers extends Array { + [amountOfTransfers: number]: IEarliestArrival; +} diff --git a/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrivalByTrip.ts b/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrivalByTrip.ts new file mode 100644 index 00000000..ac2c4bf7 --- /dev/null +++ b/src/planner/public-transport/CSA/data-structure/trips/IEarliestArrivalByTrip.ts @@ -0,0 +1,8 @@ +import IEarliestArrivalByTransfers from "./IEarliestArrivalByTransfers"; + +/** + * Stores for each gtfs:trip the earliest arrival [[IEarliestArrivalByTransfers]] to the target [[IStop]]. + */ +export default interface IEarliestArrivalByTrip { + [trip: string]: IEarliestArrivalByTransfers; +} diff --git a/src/planner/public-transport/CSA/dataStructure/EarliestArrival.ts b/src/planner/public-transport/CSA/dataStructure/EarliestArrival.ts deleted file mode 100644 index ed3c543c..00000000 --- a/src/planner/public-transport/CSA/dataStructure/EarliestArrival.ts +++ /dev/null @@ -1,6 +0,0 @@ -import IConnection from "../../../../fetcher/connections/IConnection"; - -export default class EarliestArrival { - public arrivalTime: number = Infinity; - public connection: IConnection = null; -} diff --git a/src/planner/public-transport/CSA/dataStructure/IEarliestArrivalByTrip.ts b/src/planner/public-transport/CSA/dataStructure/IEarliestArrivalByTrip.ts deleted file mode 100644 index 530c3656..00000000 --- a/src/planner/public-transport/CSA/dataStructure/IEarliestArrivalByTrip.ts +++ /dev/null @@ -1,5 +0,0 @@ -import EarliestArrival from "./EarliestArrival"; - -export default interface IEarliestArrivalByTrip { - [trip: string]: EarliestArrival[]; -} diff --git a/src/planner/public-transport/CSA/dataStructure/IProfilesByStop.ts b/src/planner/public-transport/CSA/dataStructure/IProfilesByStop.ts deleted file mode 100644 index f32a22dc..00000000 --- a/src/planner/public-transport/CSA/dataStructure/IProfilesByStop.ts +++ /dev/null @@ -1,5 +0,0 @@ -import Profile from "./Profile"; - -export default interface IProfilesByStop { - [stop: string]: Profile[]; -} diff --git a/src/planner/public-transport/CSA/dataStructure/Profile.ts b/src/planner/public-transport/CSA/dataStructure/Profile.ts deleted file mode 100644 index 20a2cf0e..00000000 --- a/src/planner/public-transport/CSA/dataStructure/Profile.ts +++ /dev/null @@ -1,15 +0,0 @@ -import IConnection from "../../../../fetcher/connections/IConnection"; - -export default class Profile { - public departureTime: number; - public arrivalTimes: number[]; - public enterConnections: IConnection[]; - public exitConnections: IConnection[]; - - constructor(maxLegs: number) { - this.departureTime = Infinity; - this.arrivalTimes = Array(maxLegs).fill(Infinity); - this.enterConnections = Array(maxLegs).fill(undefined); - this.exitConnections = Array(maxLegs).fill(undefined); - } -} diff --git a/src/planner/public-transport/CSA/util/ProfileUtil.ts b/src/planner/public-transport/CSA/util/ProfileUtil.ts new file mode 100644 index 00000000..5ae0a827 --- /dev/null +++ b/src/planner/public-transport/CSA/util/ProfileUtil.ts @@ -0,0 +1,37 @@ +import IConnection from "../../../../fetcher/connections/IConnection"; +import IProfilesByStop from "../data-structure/stops/IProfilesByStop"; + +/** + * Utility functions that can be used on the CSA profiles [[IProfilesByStop]]. + */ +export default class ProfileUtil { + + public static filterInfinity(profilesByStop: IProfilesByStop): IProfilesByStop { + const result = {}; + + for (const stop in profilesByStop) { + if (profilesByStop.hasOwnProperty(stop)) { + result[stop] = profilesByStop[stop].filter((profile) => + profile.departureTime !== Infinity, + ); + } + } + return result; + } + + public static getTransferTimes(profilesByStop: IProfilesByStop, connection: IConnection, maxLegs) { + const { arrivalStop, arrivalTime } = connection; + + let i = profilesByStop[arrivalStop].length - 1; + while (i >= 0) { + if (profilesByStop[arrivalStop][i].departureTime >= arrivalTime.getTime()) { + return profilesByStop[arrivalStop][i].getArrivalTimeByTransfers(connection["gtfs:trip"]).slice(); + } + i--; + } + return Array(maxLegs + 1).fill({ + "arrivalTime": Infinity, + "gtfs:trip": connection["gtfs:trip"], + }); + } +} diff --git a/src/planner/public-transport/CSA/utils.ts b/src/planner/public-transport/CSA/utils.ts deleted file mode 100644 index f2628172..00000000 --- a/src/planner/public-transport/CSA/utils.ts +++ /dev/null @@ -1,62 +0,0 @@ -import IConnection from "../../../fetcher/connections/IConnection"; -import IProfilesByStop from "./dataStructure/IProfilesByStop"; - -/** - * Shift a number vector to the right, - * inserting Infinity on the left side and discarding - * the last number on the right side - * @param vector: [int] - */ - -export function shiftVector(vector: number[]): number[] { - vector.unshift(Infinity); - vector.pop(); - return vector; -} - -/** - * Calculate component-wise minimum of an array of vectors - * eg minVector([[3,8,9],[4,4,4],[5,5,1]]) = [3,4,1] - * @param vectors: [[int]] - * @returns {Array} - */ -export function minVector(...vectors: number[][]): number[] { - if (!vectors || !vectors[0]) { - return []; - } - - const result: number[] = vectors[0]; - for (let vectorIndex = 1 ; vectorIndex < vectors.length ; vectorIndex++) { - for (let numberIndex = 0 ; numberIndex < vectors[vectorIndex].length ; numberIndex++) { - if (vectors[vectorIndex][numberIndex] < result[numberIndex]) { - result[numberIndex] = vectors[vectorIndex][numberIndex]; - } - } - } - return result; -} - -export function filterInfinity(profilesByStop: IProfilesByStop): IProfilesByStop { - const result = {}; - - for (const stop in profilesByStop) { - if (profilesByStop.hasOwnProperty(stop)) { - result[stop] = profilesByStop[stop].filter((profile) => - profile.departureTime !== Infinity, - ); - } - } - return result; -} - -export function evalProfile(profilesByStop: IProfilesByStop, connection: IConnection, maxLegs) { - const {arrivalStop, arrivalTime} = connection; - let i = profilesByStop[arrivalStop].length - 1; - while (i >= 0) { - if (profilesByStop[arrivalStop][i].departureTime >= arrivalTime.getTime()) { - return profilesByStop[arrivalStop][i].arrivalTimes.slice(); // Return a copy of the array - } - i--; - } - return Array(maxLegs).fill(Infinity); -} diff --git a/src/planner/public-transport/IJourneyExtractor.ts b/src/planner/public-transport/IJourneyExtractor.ts new file mode 100644 index 00000000..5febd168 --- /dev/null +++ b/src/planner/public-transport/IJourneyExtractor.ts @@ -0,0 +1,8 @@ +import { AsyncIterator } from "asynciterator"; +import IPath from "../../interfaces/IPath"; +import IResolvedQuery from "../../query-runner/IResolvedQuery"; +import IProfilesByStop from "./CSA/data-structure/stops/IProfilesByStop"; + +export default interface IJourneyExtractor { + extractJourneys: (profilesByStop: IProfilesByStop, query: IResolvedQuery) => Promise>; +} diff --git a/src/planner/public-transport/JourneyExtractionPhase.ts b/src/planner/public-transport/JourneyExtractionPhase.ts new file mode 100644 index 00000000..603882da --- /dev/null +++ b/src/planner/public-transport/JourneyExtractionPhase.ts @@ -0,0 +1,14 @@ +/** + * Signifies different phases of the journey extraction algorithm + * Dependencies of [[IJourneyExtractor]] implementations can be tagged with one of these phases, + * so the algorithm knows which dependency to use at which time. + * This is especially useful when the algorithm could potentially use different implementations of + * the same interface at each phase + */ +enum JourneyExtractionPhase { + Initial = "journeyExtractionInitial", + Transfer = "journeyExtractionTransfer", + Final = "journeyExtractionFinal", +} + +export default JourneyExtractionPhase; diff --git a/src/planner/public-transport/JourneyExtractorDefault.ts b/src/planner/public-transport/JourneyExtractorDefault.ts new file mode 100644 index 00000000..24dde2e2 --- /dev/null +++ b/src/planner/public-transport/JourneyExtractorDefault.ts @@ -0,0 +1,298 @@ +import { ArrayIterator, AsyncIterator } from "asynciterator"; +import { inject, injectable, tagged } from "inversify"; +import IConnection from "../../fetcher/connections/IConnection"; +import IStop from "../../fetcher/stops/IStop"; +import ILocation from "../../interfaces/ILocation"; +import IPath from "../../interfaces/IPath"; +import IStep from "../../interfaces/IStep"; +import ILocationResolver from "../../query-runner/ILocationResolver"; +import IResolvedQuery from "../../query-runner/IResolvedQuery"; +import TravelMode from "../../TravelMode"; +import TYPES from "../../types"; +import Iterators from "../../util/Iterators"; +import Path from "../Path"; +import IRoadPlanner from "../road/IRoadPlanner"; +import Step from "../Step"; +import IReachableStopsFinder, { IReachableStop } from "../stops/IReachableStopsFinder"; +import ReachableStopsFinderMode from "../stops/ReachableStopsFinderMode"; +import ReachableStopsSearchPhase from "../stops/ReachableStopsSearchPhase"; +import IProfilesByStop from "./CSA/data-structure/stops/IProfilesByStop"; +import ITransferProfile from "./CSA/data-structure/stops/ITransferProfile"; +import Profile from "./CSA/data-structure/stops/Profile"; +import ProfileUtil from "./CSA/util/ProfileUtil"; +import IJourneyExtractor from "./IJourneyExtractor"; +import JourneyExtractionPhase from "./JourneyExtractionPhase"; + +/** + * Creates journeys based on the profiles and query from [[PublicTransportPlannerCSAProfile]]. + * A journey is an [[IPath]] that consist of several [[IStep]]s. + * The [[JourneyExtractor]] takes care of initial, intermediate and final footpaths. + * + * @property bestArrivalTime Stores the best arrival time for each pair of departure-arrival stops. + */ +@injectable() +export default class JourneyExtractorDefault implements IJourneyExtractor { + private readonly transferRoadPlanner: IRoadPlanner; + private readonly finalRoadPlanner: IRoadPlanner; + private readonly initialReachableStopsFinder: IReachableStopsFinder; + + private readonly locationResolver: ILocationResolver; + + private bestArrivalTime: number[][] = []; + + constructor( + @inject(TYPES.RoadPlanner) + @tagged("phase", JourneyExtractionPhase.Transfer) + transferRoadPlanner: IRoadPlanner, + @inject(TYPES.RoadPlanner) + @tagged("phase", JourneyExtractionPhase.Final) + finalRoadPlanner: IRoadPlanner, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Initial) + initialReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.LocationResolver) locationResolver: ILocationResolver, + ) { + this.transferRoadPlanner = transferRoadPlanner; + this.finalRoadPlanner = finalRoadPlanner; + this.locationResolver = locationResolver; + this.initialReachableStopsFinder = initialReachableStopsFinder; + } + + public async extractJourneys( + profilesByStop: IProfilesByStop, + query: IResolvedQuery, + ): Promise> { + const filteredProfilesByStop: IProfilesByStop = ProfileUtil.filterInfinity(profilesByStop); + + const departureLocation: IStop = query.from[0] as IStop; + + const reachableStops = await this.initialReachableStopsFinder.findReachableStops( + departureLocation, + ReachableStopsFinderMode.Source, + query.maximumTransferDuration, + query.minimumWalkingSpeed, + ); + + const paths: IPath[] = []; + + for (const reachableStop of reachableStops) { + const departureStop: IStop = reachableStop.stop; + + if (!filteredProfilesByStop[departureStop.id]) { + console.warn("Can't find departure stop: " + departureStop.id); + continue; + } + + for (const profile of filteredProfilesByStop[departureStop.id]) { + if (profile.departureTime >= query.minimumDepartureTime.getTime()) { + const arrivalStop = query.to[0]; + + for (let amountOfTransfers = 0; amountOfTransfers < profile.transferProfiles.length; amountOfTransfers++) { + const transferProfile = profile.transferProfiles[amountOfTransfers]; + const enterStop = transferProfile.enterConnection && transferProfile.enterConnection.departureStop; + + if (enterStop !== departureStop.id) { + continue; + } + + if (this.checkBestArrivalTime(transferProfile, departureStop, arrivalStop)) { + try { + paths.push(await this.extractJourney( + arrivalStop, + reachableStop, + profile, + amountOfTransfers, + filteredProfilesByStop, + query, + )); + + this.setBestArrivalTime(departureStop, arrivalStop, transferProfile.arrivalTime); + } catch (e) { + console.warn(e); + } + } + + } + + } + } + } + + return new ArrayIterator(paths.reverse()); + } + + private checkBestArrivalTime( + transferProfile: ITransferProfile, + departureStop: ILocation, + arrivalStop: ILocation, + ): boolean { + + const canArrive = transferProfile.arrivalTime < Infinity; + + if (!canArrive) { + return false; + } + + const bestArrivalTimesOfDepartureStop = this.bestArrivalTime[departureStop.id]; + + if (!bestArrivalTimesOfDepartureStop) { + return true; + } + + const bestArrivalTime = bestArrivalTimesOfDepartureStop[arrivalStop.id]; + + if (!bestArrivalTime) { + return true; + } + + return transferProfile.arrivalTime < bestArrivalTime; + } + + private setBestArrivalTime(departureStop: ILocation, arrivalStop: ILocation, arrivalTime: number): void { + if (!this.bestArrivalTime[departureStop.id]) { + this.bestArrivalTime[departureStop.id] = []; + } + this.bestArrivalTime[departureStop.id][arrivalStop.id] = arrivalTime; + } + + private async extractJourney( + arrivalStop: ILocation, + reachableStop: IReachableStop, + profile: Profile, + transfers: number, + profilesByStop: IProfilesByStop, + query: IResolvedQuery, + ): Promise { + let shouldReturn = true; + + // Extract journey for amount of transfers + const path: Path = Path.create(); + + let currentProfile = profile; + let remainingTransfers = transfers; + + if (reachableStop.duration > 0) { + const currentTransferProfile = profile.transferProfiles[remainingTransfers]; + + this.addInitialFootpath( + path, + currentTransferProfile, + reachableStop, + query.from[0], + ); + } + + while (remainingTransfers >= 0) { + // Construct and push step + const currentTransferProfile = currentProfile.transferProfiles[remainingTransfers]; + + const enterConnection: IConnection = currentTransferProfile.enterConnection; + const exitConnection: IConnection = currentTransferProfile.exitConnection; + + const step: IStep = Step.createFromConnections(enterConnection, exitConnection); + + step.startLocation = await this.locationResolver.resolve(step.startLocation.id); + step.stopLocation = await this.locationResolver.resolve(step.stopLocation.id); + + path.addStep(step); + + remainingTransfers--; + if (remainingTransfers >= 0) { + const nextProfile = profilesByStop[step.stopLocation.id]; + + let i = nextProfile.length - 1; + let found = false; + + while (!found && i >= 0) { + const nextTransferProfile = nextProfile[i].transferProfiles[remainingTransfers]; + const connection = nextTransferProfile.enterConnection; + + if (connection) { + const from = await this.locationResolver.resolve(step.stopLocation.id); + const to = await this.locationResolver.resolve(connection.departureStop); + + const walkingResult = await this.transferRoadPlanner.plan({ + from: [from], + to: [to], + minimumWalkingSpeed: query.minimumWalkingSpeed, + maximumWalkingSpeed: query.maximumWalkingSpeed, + }); + + // Get first path + const walkingPath: IPath = await Iterators.getFirst(walkingResult); + + if (walkingPath && walkingPath.steps[0] && + connection.departureTime.getTime() >= step.stopTime.getTime() + + walkingPath.steps[0].duration.minimum + ) { + found = true; + path.addStep(walkingPath.steps[0]); + currentProfile = nextProfile[i]; + } + } + + i--; + } + + if (!found) { + return Promise.reject("Can't reach arrival stop: " + arrivalStop.id + ", transfers: " + transfers); + } + } + } + + if (path.steps[path.steps.length - 1].stopLocation.id !== arrivalStop.id) { + shouldReturn = await this.addFinalFootpath(path, arrivalStop, query); + } + + if (!shouldReturn) { + return Promise.reject("Can't reach arrival stop: " + arrivalStop.id + ", transfers: " + transfers); + } + + return path as IPath; + } + + private addInitialFootpath( + path: Path, + transferProfile: ITransferProfile, + reachableStop: IReachableStop, + startLocation: ILocation, + ): void { + const enterConnection: IConnection = transferProfile.enterConnection; + const stopTime = enterConnection.departureTime; + const startTime = new Date(stopTime.valueOf() - reachableStop.duration); + + const step = Step.create( + startLocation, + reachableStop.stop as ILocation, + TravelMode.Walking, + { minimum: reachableStop.duration }, + startTime, + enterConnection.departureTime, + undefined, + ); + + path.addStep(step); + } + + private async addFinalFootpath(path: Path, arrivalStop: ILocation, query: IResolvedQuery): Promise { + const lastStep = path.steps[path.steps.length - 1]; + + const fromLocation = await this.locationResolver.resolve(lastStep.stopLocation.id); + const toLocation = await this.locationResolver.resolve(arrivalStop); + + const walkingResult = await this.finalRoadPlanner.plan({ + from: [fromLocation], + to: [toLocation], + minimumWalkingSpeed: query.minimumWalkingSpeed, + maximumWalkingSpeed: query.maximumWalkingSpeed, + }); + + if (walkingResult && walkingResult[0] && walkingResult[0].steps[0] && + query.maximumArrivalTime.getTime() >= lastStep.stopTime.getTime() + + walkingResult[0].steps[0].duration.minimum) { + path.addStep(walkingResult[0].steps[0]); + return true; + } + return false; + } +} diff --git a/src/planner/public-transport/PublicTransportPlannerCSAProfile.test.ts b/src/planner/public-transport/PublicTransportPlannerCSAProfile.test.ts new file mode 100644 index 00000000..760564ad --- /dev/null +++ b/src/planner/public-transport/PublicTransportPlannerCSAProfile.test.ts @@ -0,0 +1,378 @@ +import "jest"; +import LDFetch from "ldfetch"; +import ConnectionsFetcherLazy from "../../fetcher/connections/ld-fetch/ConnectionsFetcherLazy"; +import ConnectionsFetcherNMBSTest from "../../fetcher/connections/tests/ConnectionsFetcherNMBSTest"; +import connectionsIngelmunsterGhent from "../../fetcher/connections/tests/data/ingelmunster-ghent"; +import connectionsJoining from "../../fetcher/connections/tests/data/joining"; +import connectionsSplitting from "../../fetcher/connections/tests/data/splitting"; +import StopsFetcherLDFetch from "../../fetcher/stops/ld-fetch/StopsFetcherLDFetch"; +import IPath from "../../interfaces/IPath"; +import IQuery from "../../interfaces/IQuery"; +import IStep from "../../interfaces/IStep"; +import Planner from "../../Planner"; +import IResolvedQuery from "../../query-runner/IResolvedQuery"; +import LocationResolverDefault from "../../query-runner/LocationResolverDefault"; +import QueryRunnerDefault from "../../query-runner/QueryRunnerDefault"; +import TravelMode from "../../TravelMode"; +import Iterators from "../../util/Iterators"; +import Units from "../../util/Units"; +import RoadPlannerBirdsEye from "../road/RoadPlannerBirdsEye"; +import ReachableStopsFinderBirdsEyeCached from "../stops/ReachableStopsFinderBirdsEyeCached"; +import JourneyExtractorDefault from "./JourneyExtractorDefault"; +import PublicTransportPlannerCSAProfile from "./PublicTransportPlannerCSAProfile"; + +describe("[PublicTransportPlannerCSAProfile]", () => { + describe("mock data", () => { + jest.setTimeout(100000); + + const createCSA = (connections) => { + const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + + const connectionFetcher = new ConnectionsFetcherNMBSTest(connections); + connectionFetcher.setConfig({ backward: true }); + + const stopsFetcher = new StopsFetcherLDFetch(ldFetch); + stopsFetcher.setPrefix("http://irail.be/stations/NMBS/"); + stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); + + const locationResolver = new LocationResolverDefault(stopsFetcher); + const reachableStopsFinder = new ReachableStopsFinderBirdsEyeCached(stopsFetcher); + const roadPlanner = new RoadPlannerBirdsEye(); + const journeyExtractor = new JourneyExtractorDefault( + roadPlanner, + roadPlanner, + reachableStopsFinder, + locationResolver, + ); + + return new PublicTransportPlannerCSAProfile( + connectionFetcher, + locationResolver, + reachableStopsFinder, + reachableStopsFinder, + journeyExtractor, + ); + }; + + describe("basic test", () => { + let result: IPath[]; + + const query: IResolvedQuery = { + publicTransportOnly: true, + from: [{ id: "http://irail.be/stations/NMBS/008896925", latitude: 50.914326, longitude: 3.255416 }], + to: [{ id: "http://irail.be/stations/NMBS/008892007", latitude: 51.035896, longitude: 3.710675 }], + minimumDepartureTime: new Date("2018-11-06T09:00:00.000Z"), + maximumArrivalTime: new Date("2018-11-06T19:00:00.000Z"), + maximumTransfers: 8, + }; + + beforeAll(async () => { + const CSA = createCSA(connectionsIngelmunsterGhent); + const iterator = await CSA.plan(query); + result = await Iterators.toArray(iterator); + }); + + it("Correct departure and arrival stop", () => { + expect(result).toBeDefined(); + + for (const path of result) { + expect(path.steps).toBeDefined(); + expect(path.steps[0]).toBeDefined(); + expect(query.from.map((from) => from.id)).toContain(path.steps[0].startLocation.id); + expect(query.to.map((to) => to.id)).toContain(path.steps[path.steps.length - 1].stopLocation.id); + } + }); + }); + + describe("splitting", () => { + let result: IPath[]; + + const query: IResolvedQuery = { + publicTransportOnly: true, + from: [{ id: "http://irail.be/stations/NMBS/008821006" }], + to: [{ id: "http://irail.be/stations/NMBS/008812005" }], + minimumDepartureTime: new Date("2017-12-19T15:50:00.000Z"), + maximumArrivalTime: new Date("2017-12-19T16:50:00.000Z"), + maximumTransfers: 1, + }; + + beforeAll(async () => { + const CSA = createCSA(connectionsSplitting); + const iterator = await CSA.plan(query); + result = await Iterators.toArray(iterator); + }); + + it("Correct departure and arrival stop", () => { + expect(result).toBeDefined(); + expect(result.length).toBeGreaterThanOrEqual(1); + + for (const path of result) { + expect(path.steps).toBeDefined(); + + expect(path.steps.length).toEqual(1); + expect(path.steps[0]).toBeDefined(); + + expect(query.from.map((from) => from.id)).toContain(path.steps[0].startLocation.id); + expect(query.to.map((to) => to.id)).toContain(path.steps[0].stopLocation.id); + } + }); + }); + + describe("joining", () => { + let result: IPath[]; + + const query: IResolvedQuery = { + publicTransportOnly: true, + from: [{ id: "http://irail.be/stations/NMBS/008812005" }], + to: [{ id: "http://irail.be/stations/NMBS/008821006" }], + minimumDepartureTime: new Date("2017-12-19T16:20:00.000Z"), + maximumArrivalTime: new Date("2017-12-19T16:50:00.000Z"), + maximumTransfers: 1, + }; + + beforeAll(async () => { + const CSA = createCSA(connectionsJoining); + const iterator = await CSA.plan(query); + result = await Iterators.toArray(iterator); + }); + + it("Correct departure and arrival stop", () => { + expect(result).toBeDefined(); + expect(result.length).toBeGreaterThanOrEqual(1); + + for (const path of result) { + expect(path.steps).toBeDefined(); + + expect(path.steps.length).toEqual(1); + expect(path.steps[0]).toBeDefined(); + + expect(query.from.map((from) => from.id)).toContain(path.steps[0].startLocation.id); + expect(query.to.map((to) => to.id)).toContain(path.steps[0].stopLocation.id); + } + }); + }); + }); + + describe("real-time data", () => { + const createQueryRunner = () => { + const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + + const connectionFetcher = new ConnectionsFetcherLazy(ldFetch); + connectionFetcher.setTravelMode(TravelMode.Train); + connectionFetcher.setAccessUrl("https://graph.irail.be/sncb/connections"); + + const stopsFetcher = new StopsFetcherLDFetch(ldFetch); + stopsFetcher.setPrefix("http://irail.be/stations/NMBS/"); + stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); + + const locationResolver = new LocationResolverDefault(stopsFetcher); + const reachableStopsFinder = new ReachableStopsFinderBirdsEyeCached(stopsFetcher); + const roadPlanner = new RoadPlannerBirdsEye(); + const journeyExtractor = new JourneyExtractorDefault( + roadPlanner, + roadPlanner, + reachableStopsFinder, + locationResolver, + ); + + const CSA = new PublicTransportPlannerCSAProfile( + connectionFetcher, + locationResolver, + reachableStopsFinder, + reachableStopsFinder, + journeyExtractor, + ); + + return new QueryRunnerDefault(locationResolver, CSA); + }; + + const checkStops = (result, query) => { + expect(result).toBeDefined(); + expect(result.length).toBeGreaterThanOrEqual(1); + + for (const path of result) { + expect(path.steps).toBeDefined(); + + expect(path.steps.length).toBeGreaterThanOrEqual(1); + + let currentLocation = query.from; + path.steps.forEach((step: IStep) => { + expect(step).toBeDefined(); + expect(currentLocation).toEqual(step.startLocation.id); + currentLocation = step.stopLocation.id; + }); + + expect(query.to).toEqual(currentLocation); + } + }; + + const checkTimes = (result, minimumDepartureTime, maximumArrivalTime) => { + expect(result).toBeDefined(); + expect(result.length).toBeGreaterThanOrEqual(1); + + for (const path of result) { + expect(path.steps).toBeDefined(); + + expect(path.steps.length).toBeGreaterThanOrEqual(1); + expect(path.steps[0]).toBeDefined(); + expect(path.steps[path.steps.length - 1]).toBeDefined(); + + let currentTime = minimumDepartureTime.getTime(); + path.steps.forEach((step: IStep) => { + expect(step).toBeDefined(); + if (step.travelMode === TravelMode.Walking) { + currentTime += step.duration.minimum; + } else { + expect(currentTime).toBeLessThanOrEqual(step.startTime.getTime()); + currentTime = step.stopTime.getTime(); + } + }); + + expect(path.steps[0].startTime.getTime()).toBeGreaterThanOrEqual(minimumDepartureTime.getTime()); + expect(currentTime).toBeLessThanOrEqual(maximumArrivalTime.getTime()); + } + }; + + describe("Arrival Thu Nov 29 2018 20:01:27 GMT+0100", () => { + jest.setTimeout(100000); + + const minimumDepartureTime = new Date(1543518087748); + minimumDepartureTime.setHours(minimumDepartureTime.getHours() - 2); + + const maximumArrivalTime = new Date(1543518087748); + + const query: IQuery = { + publicTransportOnly: true, + from: "http://irail.be/stations/NMBS/008896925", // Ingelmunster + to: "http://irail.be/stations/NMBS/008892007", // Antwerpen + maximumArrivalTime, + minimumDepartureTime, + }; + let result: IPath[]; + + beforeAll(async () => { + const queryRunner = createQueryRunner(); + const iterator = await queryRunner.run(query); + + result = await Iterators.toArray(iterator); + }); + + it("Correct departure and arrival stop", () => { + checkStops(result, query); + }); + + it("Correct departure and arrival time", () => { + checkTimes(result, minimumDepartureTime, maximumArrivalTime); + }); + }); + + describe("Departure Time now - Arrival Time now+2h", () => { + jest.setTimeout(100000); + + const minimumDepartureTime = new Date(); + const maximumArrivalTime = new Date(); + maximumArrivalTime.setHours(maximumArrivalTime.getHours() + 2); + + const query: IQuery = { + publicTransportOnly: true, + from: "http://irail.be/stations/NMBS/008896925", // Ingelmunster + to: "http://irail.be/stations/NMBS/008892007", // Antwerpen + maximumArrivalTime, + minimumDepartureTime, + }; + let result: IPath[]; + + beforeAll(async () => { + const queryRunner = createQueryRunner(); + const iterator = await queryRunner.run(query); + + result = await Iterators.toArray(iterator); + }); + + it("Correct departure and arrival stop", () => { + checkStops(result, query); + }); + + it("Correct departure and arrival time", () => { + checkTimes(result, minimumDepartureTime, maximumArrivalTime); + }); + }); + + describe("Initial walking possibilities in Brussels", () => { + jest.setTimeout(100000); + + const minimumDepartureTime = new Date(); + const maximumArrivalTime = new Date(); + maximumArrivalTime.setHours(maximumArrivalTime.getHours() + 3); + + const query: IQuery = { + publicTransportOnly: true, + from: "http://irail.be/stations/NMBS/008812005", // Brussels North + to: "http://irail.be/stations/NMBS/008892007", // Ghent-Sint-Pieters + maximumArrivalTime, + minimumDepartureTime, + }; + let result: IPath[]; + + beforeAll(async () => { + const queryRunner = createQueryRunner(); + const iterator = await queryRunner.run(query); + + result = await Iterators.toArray(iterator); + }); + + it("Correct departure and arrival stop", () => { + checkStops(result, query); + }); + + it("Correct departure and arrival time", () => { + checkTimes(result, minimumDepartureTime, maximumArrivalTime); + }); + }); + + describe("Exponential query runner", () => { + jest.setTimeout(100000); + let publicTransportResult; + + const query = { + publicTransportOnly: true, + from: "http://irail.be/stations/NMBS/008896925", // Ingelmunster + to: "http://irail.be/stations/NMBS/008892007", // Ghent-Sint-Pieters + minimumDepartureTime: new Date(), + maximumTransferDuration: Units.fromHours(.5), + }; + + const result: IPath[] = []; + + beforeAll(async (done) => { + const planner = new Planner(); + publicTransportResult = await planner.query(query); + + let i = 0; + publicTransportResult.on("readable", () => { + let path = publicTransportResult.read(); + if (path) { + result.push(path); + } + + while (path && i < 10) { + i++; + path = publicTransportResult.read(); + + if (path) { + result.push(path); + } + } + + if (i === 10) { + done(); + } + }); + }); + + it("Correct departure and arrival stop", () => { + checkStops(result, query); + }); + }); + }); +}); diff --git a/src/planner/public-transport/PublicTransportPlannerCSAProfile.ts b/src/planner/public-transport/PublicTransportPlannerCSAProfile.ts index 1ac80079..b2e696a5 100644 --- a/src/planner/public-transport/PublicTransportPlannerCSAProfile.ts +++ b/src/planner/public-transport/PublicTransportPlannerCSAProfile.ts @@ -1,220 +1,384 @@ -import { inject, injectable } from "inversify"; +import { AsyncIterator } from "asynciterator"; +import { inject, injectable, tagged } from "inversify"; import IConnection from "../../fetcher/connections/IConnection"; -import IConnectionsFetcher from "../../fetcher/connections/IConnectionsFetcher"; +import IConnectionsProvider from "../../fetcher/connections/IConnectionsProvider"; +import IStop from "../../fetcher/stops/IStop"; import IPath from "../../interfaces/IPath"; +import { DurationMs } from "../../interfaces/units"; import ILocationResolver from "../../query-runner/ILocationResolver"; import IResolvedQuery from "../../query-runner/IResolvedQuery"; import TYPES from "../../types"; -import IRoadPlanner from "../road/IRoadPlanner"; -import IEarliestArrival from "./CSA/dataStructure/EarliestArrival"; -import EarliestArrival from "./CSA/dataStructure/EarliestArrival"; -import IEarliestArrivalByTrip from "./CSA/dataStructure/IEarliestArrivalByTrip"; -import IProfilesByStop from "./CSA/dataStructure/IProfilesByStop"; -import Profile from "./CSA/dataStructure/Profile"; -import JourneyExtractor from "./CSA/JourneyExtractor"; -import { evalProfile, minVector, shiftVector } from "./CSA/utils"; +import Vectors from "../../util/Vectors"; +import IReachableStopsFinder from "../stops/IReachableStopsFinder"; +import ReachableStopsFinderMode from "../stops/ReachableStopsFinderMode"; +import ReachableStopsSearchPhase from "../stops/ReachableStopsSearchPhase"; +import IArrivalTimeByTransfers from "./CSA/data-structure/IArrivalTimeByTransfers"; +import IProfilesByStop from "./CSA/data-structure/stops/IProfilesByStop"; +import ITransferProfile from "./CSA/data-structure/stops/ITransferProfile"; +import Profile from "./CSA/data-structure/stops/Profile"; +import EarliestArrivalByTransfers from "./CSA/data-structure/trips/EarliestArrivalByTransfers"; +import IEarliestArrivalByTransfers from "./CSA/data-structure/trips/IEarliestArrivalByTransfers"; +import IEarliestArrivalByTrip from "./CSA/data-structure/trips/IEarliestArrivalByTrip"; +import ProfileUtil from "./CSA/util/ProfileUtil"; +import IJourneyExtractor from "./IJourneyExtractor"; import IPublicTransportPlanner from "./IPublicTransportPlanner"; +/** + * An implementation of the Connection Scan Algorithm (CSA). + * + * @implements [[IPublicTransportPlanner]] + * @property profilesByStop Describes the CSA profiles for each scanned stop. + * @property earliestArrivalByTrip Describes the earliest arrival time for each scanned trip. + * @property durationToTargetByStop Describes the walking duration to the target stop for a scanned stop. + * + * @returns multiple [[IPath]]s that consist of several [[IStep]]s. + */ @injectable() export default class PublicTransportPlannerCSAProfile implements IPublicTransportPlanner { - public readonly connectionsFetcher: IConnectionsFetcher; - public readonly roadPlanner: IRoadPlanner; - public readonly locationResolver: ILocationResolver; - - private readonly journeyExtractor: JourneyExtractor; + private readonly connectionsProvider: IConnectionsProvider; + private readonly locationResolver: ILocationResolver; + private readonly finalReachableStopsFinder: IReachableStopsFinder; + private readonly transferReachableStopsFinder: IReachableStopsFinder; + private readonly journeyExtractor: IJourneyExtractor; private profilesByStop: IProfilesByStop = {}; // S private earliestArrivalByTrip: IEarliestArrivalByTrip = {}; // T - - private D: number[] = []; - private maxLegs: number = 8; + private durationToTargetByStop: DurationMs[] = []; + private gtfsTripByConnection = {}; private query: IResolvedQuery; + private connectionsIterator: AsyncIterator; constructor( - @inject(TYPES.ConnectionsFetcher) connectionsFetcher: IConnectionsFetcher, - @inject(TYPES.RoadPlanner) roadPlanner: IRoadPlanner, + @inject(TYPES.ConnectionsProvider) connectionsProvider: IConnectionsProvider, @inject(TYPES.LocationResolver) locationResolver: ILocationResolver, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Transfer) + transferReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Final) + finalReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.JourneyExtractor) journeyExtractor: IJourneyExtractor, ) { - this.connectionsFetcher = connectionsFetcher; - this.roadPlanner = roadPlanner; + this.connectionsProvider = connectionsProvider; this.locationResolver = locationResolver; - this.journeyExtractor = new JourneyExtractor(roadPlanner, locationResolver); + this.transferReachableStopsFinder = transferReachableStopsFinder; + this.finalReachableStopsFinder = finalReachableStopsFinder; + this.journeyExtractor = journeyExtractor; + } + + public async plan(query: IResolvedQuery): Promise> { + this.query = query; + this.setBounds(); - const upperBoundDate = new Date(); - upperBoundDate.setHours(upperBoundDate.getHours() + 2 ); + return this.calculateJourneys(); + } + + private setBounds() { + const { + minimumDepartureTime: lowerBoundDate, + maximumArrivalTime: upperBoundDate, + } = this.query; - this.connectionsFetcher.setConfig({ + this.connectionsProvider.setConfig({ backward: true, - upperBoundDate, // TODO what's the upperBoundDate. + upperBoundDate, + lowerBoundDate, }); } - public async plan(query: IResolvedQuery): Promise { - return await this.calculateJourneys(query); + private async calculateJourneys(): Promise> { + await this.initDurationToTargetByStop(); + + this.connectionsIterator = this.connectionsProvider.createIterator(); + + const self = this; + + return new Promise((resolve, reject) => { + + const done = () => { + self.journeyExtractor.extractJourneys(self.profilesByStop, self.query) + .then((resultIterator) => { + resolve(resultIterator); + }); + }; + + this.connectionsIterator.on("readable", () => + self.processNextConnection(done), + ); + + this.connectionsIterator.on("end", () => done()); + + }) as Promise>; } - private async calculateJourneys(query: IResolvedQuery): Promise { - this.query = query; - const earliestDepartureTime = new Date(); + private processNextConnection(done: () => void) { + const connection = this.connectionsIterator.read(); + + if (connection) { + if (connection.arrivalTime > this.query.maximumArrivalTime) { + this.maybeProcessNextConnection(done); + return; + } - for await (const connection of this.connectionsFetcher) { - if (connection.departureTime < earliestDepartureTime) { - break; + if (connection.departureTime < this.query.minimumDepartureTime) { + this.connectionsIterator.close(); + done(); + return; } this.discoverConnection(connection); - const earliestArrivalTime = this.calculateEarliestArrivalTime(connection); + const earliestArrivalTime = this.calculateEarliestArrivalTime(connection); this.updateEarliestArrivalByTrip(connection, earliestArrivalTime); if (!this.isDominated(connection, earliestArrivalTime)) { - this.incorporateForFootpaths(connection, earliestArrivalTime); + this.getFootpathsForDepartureStop(connection, earliestArrivalTime) + .then(() => this.maybeProcessNextConnection(done)); + + } else { + this.maybeProcessNextConnection(done); } } + } - return await this.journeyExtractor.extractJourneys( - this.profilesByStop, - query.from[0], - query.to[0], - earliestDepartureTime, - ); + private maybeProcessNextConnection(done: () => void) { + if (!this.connectionsIterator.closed) { + this.processNextConnection(done); + } } private discoverConnection(connection: IConnection) { + this.gtfsTripByConnection[connection.id] = connection["gtfs:trip"]; + [connection.departureStop, connection.arrivalStop].forEach((stop) => { if (!this.profilesByStop[stop]) { - this.profilesByStop[stop] = [new Profile(this.maxLegs)]; + this.profilesByStop[stop] = [Profile.create(this.query.maximumTransfers)]; } }); if (!this.earliestArrivalByTrip[connection["gtfs:trip"]]) { - this.earliestArrivalByTrip[connection["gtfs:trip"]] = Array(this.maxLegs).fill(new EarliestArrival()); + this.earliestArrivalByTrip[connection["gtfs:trip"]] = EarliestArrivalByTransfers.create( + this.query.maximumTransfers, + ); } } - private calculateEarliestArrivalTime(connection: IConnection): number[] { - const t1 = this.walkToTarget(connection); - const t2 = this.remainSeated(connection); - const t3 = this.takeTransfer(connection); + private getTripIdsFromConnection(connection: IConnection): string[] { + const tripIds = [connection["gtfs:trip"]]; - return minVector(t1, t2, t3); + if (!connection.nextConnection) { + return tripIds; + } + + for (const connectionId of connection.nextConnection) { + const tripId = this.gtfsTripByConnection[connectionId]; + if (tripIds.indexOf(tripId) === -1) { + tripIds.push(this.gtfsTripByConnection[connectionId]); + } + } + + return tripIds; } - private walkToTarget(connection: IConnection): number[] { - let walkingTimeToTarget = this.D[connection.arrivalStop]; // TODO get duration. + private calculateEarliestArrivalTime(connection: IConnection): IArrivalTimeByTransfers { + const remainSeatedTime = this.remainSeated(connection); + if (connection["gtfs:dropOffType"] === "gtfs:NotAvailable") { + return remainSeatedTime; + } - if (connection.arrivalStop === this.query.to[0].id) { // not needed. - walkingTimeToTarget = 0; + const walkToTargetTime = this.walkToTarget(connection); + const takeTransferTime = this.takeTransfer(connection); + + return Vectors.minVector((c) => c.arrivalTime, walkToTargetTime, remainSeatedTime, takeTransferTime); + } + + private async initDurationToTargetByStop(): Promise { + const arrivalStop: IStop = this.query.to[0] as IStop; + + const reachableStops = await this.finalReachableStopsFinder + .findReachableStops( + arrivalStop, + ReachableStopsFinderMode.Target, + this.query.maximumTransferDuration, + this.query.minimumWalkingSpeed, + ); + + for (const reachableStop of reachableStops) { + this.durationToTargetByStop[reachableStop.stop.id] = reachableStop.duration; } + } + + private walkToTarget(connection: IConnection): IArrivalTimeByTransfers { + const walkingTimeToTarget = this.durationToTargetByStop[connection.arrivalStop]; if (walkingTimeToTarget === undefined) { - return Array(this.maxLegs).fill(Infinity); + return Array(this.query.maximumTransfers + 1).fill({ + "arrivalTime": Infinity, + "gtfs:trip": connection["gtfs:trip"], + }); } - return Array(this.maxLegs).fill(connection.arrivalTime.getTime() + walkingTimeToTarget); + return Array(this.query.maximumTransfers + 1).fill({ + "arrivalTime": connection.arrivalTime.getTime() + walkingTimeToTarget, + "gtfs:trip": connection["gtfs:trip"], + }); } - private remainSeated(connection: IConnection): number[] { - return this.earliestArrivalByTrip[connection["gtfs:trip"]].map((trip) => trip.arrivalTime); + private remainSeated(connection: IConnection): IArrivalTimeByTransfers { + const tripIds = this.getTripIdsFromConnection(connection); + const earliestArrivalTimeByTransfers: IArrivalTimeByTransfers = []; + + for (let amountOfTransfers = 0; amountOfTransfers < this.query.maximumTransfers + 1; amountOfTransfers++) { + const earliestArrivalTime = earliestArrivalTimeByTransfers[amountOfTransfers]; + let minimumArrivalTime = earliestArrivalTime && earliestArrivalTime.arrivalTime; + + for (const tripId of tripIds) { + const tripArrivalTime = this.earliestArrivalByTrip[tripId][amountOfTransfers].arrivalTime; + + if (!minimumArrivalTime || tripArrivalTime < minimumArrivalTime) { + earliestArrivalTimeByTransfers[amountOfTransfers] = { + "arrivalTime": tripArrivalTime, + "gtfs:trip": tripId, + }; + minimumArrivalTime = tripArrivalTime; + } + } + + } + + return earliestArrivalTimeByTransfers; } - private takeTransfer(connection: IConnection): number[] { - return shiftVector(evalProfile(this.profilesByStop, connection, this.maxLegs)); + private takeTransfer(connection: IConnection): IArrivalTimeByTransfers { + return Vectors.shiftVector( + ProfileUtil.getTransferTimes(this.profilesByStop, connection, this.query.maximumTransfers), + { "arrivalTime": Infinity, "gtfs:trip": connection["gtfs:trip"] }, + ); } - private updateEarliestArrivalByTrip(connection: IConnection, currentArrivalTimeByTransfers: number[]): void { - const earliestArrivalByTransfers: IEarliestArrival[] = this.earliestArrivalByTrip[connection["gtfs:trip"]]; + private updateEarliestArrivalByTrip( + connection: IConnection, + arrivalTimeByTransfers: IArrivalTimeByTransfers, + ): void { + const tripIds = this.getTripIdsFromConnection(connection); + + const earliestArrivalByTransfers: IEarliestArrivalByTransfers = arrivalTimeByTransfers.map( + (arrivalTime, amountOfTransfers: number) => { + const tripId: string = arrivalTime["gtfs:trip"]; + return this.earliestArrivalByTrip[tripId][amountOfTransfers]; + }, + ); - this.earliestArrivalByTrip[connection["gtfs:trip"]] = earliestArrivalByTransfers.map( - (earliestArrival, transfer) => { - if (currentArrivalTimeByTransfers[transfer] < earliestArrival.arrivalTime) { - return {connection, arrivalTime: currentArrivalTimeByTransfers[transfer]}; - } - return earliestArrival; - }); + for (const tripId of tripIds) { + this.earliestArrivalByTrip[tripId] = EarliestArrivalByTransfers.createByConnection( + earliestArrivalByTransfers, + connection, + arrivalTimeByTransfers, + ); + } } - private isDominated(connection: IConnection, currentArrivalTimeByTransfers: number[]): boolean { - const depProfile = this.profilesByStop[connection.departureStop]; - const earliestProfileEntry = depProfile[depProfile.length - 1]; + private isDominated(connection: IConnection, arrivalTimeByTransfers: IArrivalTimeByTransfers): boolean { + const departureProfile = this.profilesByStop[connection.departureStop]; + const earliestProfileEntry = departureProfile[departureProfile.length - 1]; - return earliestProfileEntry.arrivalTimes.reduce((memo, arrivalTime, transfer) => - memo && arrivalTime <= currentArrivalTimeByTransfers[transfer] - , true); + return earliestProfileEntry.isDominated(arrivalTimeByTransfers); } - private incorporateForFootpaths(connection: IConnection, currentArrivalTimeByTransfers: number[]): void { + private async getFootpathsForDepartureStop( + connection: IConnection, + currentArrivalTimeByTransfers: IArrivalTimeByTransfers, + ): Promise { const depProfile: Profile[] = this.profilesByStop[connection.departureStop]; const earliestProfileEntry = depProfile[depProfile.length - 1]; - const minVectorTimes = minVector(currentArrivalTimeByTransfers, earliestProfileEntry.arrivalTimes); - - // For all footpaths with f_arr_stop = c_dep_stop - // TODO getInterstopDistance - const ISDs = [{stop1: connection.departureStop, stop2: connection.departureStop, duration: 60000}]; - ISDs.forEach((ISD) => { - // stop is f_dep_stop, the stop of the ISD that is _not_ connection.dep.stop - let stop = ISD.stop1; - if (stop === connection.departureStop) { - stop = ISD.stop2; - } + const earliestArrivalTimeByTransfers = Vectors.minVector( + (c) => c.arrivalTime, + currentArrivalTimeByTransfers, + earliestProfileEntry.getArrivalTimeByTransfers(), + ); + + const departureStop = await this.locationResolver.resolve(connection.departureStop); + const reachableStops = await this.transferReachableStopsFinder.findReachableStops( + departureStop as IStop, + ReachableStopsFinderMode.Source, + this.query.maximumTransferDuration, + this.query.minimumWalkingSpeed, + ); + + reachableStops.forEach((reachableStop) => { // Incorporate (c_dep_time - f_dur, t_c) into profile of S[f_dep_stop] - this.incorporateInProfile(connection, ISD, stop, minVectorTimes); + this.incorporateInProfile(connection, reachableStop.duration, reachableStop.stop, earliestArrivalTimeByTransfers); }); } - private incorporateInProfile(connection: IConnection, ISD, stop: string, minVectorTimes: number[]) { - let ISDDepProfile = this.profilesByStop[stop]; // S[f_dep_stop] - // S[f_dep_stop] might be undefined (open world), in that case initialize its profile entry - if (ISDDepProfile === undefined) { - ISDDepProfile = this.profilesByStop[stop] = [new Profile(this.maxLegs)]; - } - const ISDDepEarliestEntry = ISDDepProfile[ISDDepProfile.length - 1]; // earliest dep time - // Enter and exit connections are journey pointers - const enterConnections = []; - const exitConnections = []; - - // For each amount of legs - for (let i = 0; i < this.maxLegs; i++) { - // If the new arrival time is better, update journey pointers - // Else, keep old journey pointers - if (minVectorTimes[i] < ISDDepEarliestEntry.arrivalTimes[i]) { - enterConnections[i] = connection; - exitConnections[i] = this.earliestArrivalByTrip[connection["gtfs:trip"]][i].connection; - if (exitConnections[i] === null) { - // This means the exit connection is the enter connection, - // and tripStructure[connection.tripId] hasn't been initialized properly yet. - exitConnections[i] = connection; - } - } else { - enterConnections[i] = ISDDepEarliestEntry.enterConnections[i]; - exitConnections[i] = ISDDepEarliestEntry.exitConnections[i]; - } + private incorporateInProfile( + connection: IConnection, + duration: DurationMs, + stop: IStop, + arrivalTimeByTransfers: IArrivalTimeByTransfers, + ) { + let profilesByDepartureStop = this.profilesByStop[stop.id]; + + if (!profilesByDepartureStop) { + profilesByDepartureStop = this.profilesByStop[stop.id] = [Profile.create(this.query.maximumTransfers)]; } + const earliestDepTimeProfile = profilesByDepartureStop[profilesByDepartureStop.length - 1]; // If arrival times for all numbers of legs are equal to the earliest entry, this // entry is redundant - let redundant = true; - for (let i = 0; i < this.maxLegs; i++) { - redundant = redundant && minVectorTimes[i] >= ISDDepEarliestEntry.arrivalTimes[i]; - } - if (!redundant) { - // If the new departure time is equal, update the profile entry - // Else, insert a new entry - const departureTime = connection.departureTime.getTime() - ISD.duration; // Calculate c_dep_time - f_dur - const entry = { - departureTime, - arrivalTimes: minVectorTimes, - enterConnections, - exitConnections, - }; + if (!earliestDepTimeProfile.isDominated(arrivalTimeByTransfers)) { + const currentTransferProfiles = earliestDepTimeProfile.transferProfiles; + const transferProfiles = []; + + for (let amountOfTransfers = 0; amountOfTransfers < currentTransferProfiles.length; amountOfTransfers++) { + const transferProfile: ITransferProfile = currentTransferProfiles[amountOfTransfers]; + + const newTransferProfile: ITransferProfile = { + exitConnection: undefined, + enterConnection: undefined, + arrivalTime: Infinity, + }; + + const possibleExitConnection = this.earliestArrivalByTrip[connection["gtfs:trip"]] + [amountOfTransfers].connection || connection; + + if ( + arrivalTimeByTransfers[amountOfTransfers].arrivalTime < transferProfile.arrivalTime && + connection["gtfs:pickupType"] !== "gtfs:NotAvailable" && + possibleExitConnection["gtfs:dropOfType"] !== "gtfs:NotAvailable" + ) { + newTransferProfile.enterConnection = connection; + newTransferProfile.exitConnection = possibleExitConnection; + } else { + newTransferProfile.enterConnection = transferProfile.enterConnection; + newTransferProfile.exitConnection = transferProfile.exitConnection; + } - if (ISDDepEarliestEntry.departureTime !== departureTime) { - ISDDepProfile.push(entry); + if (newTransferProfile.exitConnection && newTransferProfile.enterConnection) { + newTransferProfile.arrivalTime = arrivalTimeByTransfers[amountOfTransfers].arrivalTime; + } + + transferProfiles.push(newTransferProfile); + } + + const departureTime = connection.departureTime.getTime() - duration; + const newProfile: Profile = Profile.createFromTransfers(departureTime, transferProfiles); + + let i = profilesByDepartureStop.length - 1; + let earliestProfile = profilesByDepartureStop[i]; + + if (earliestProfile.departureTime === Infinity) { + profilesByDepartureStop[i] = newProfile; } else { - ISDDepProfile[ISDDepProfile.length - 1] = entry; + while (i > 0 && earliestProfile.departureTime < departureTime) { + profilesByDepartureStop[i + 1] = earliestProfile; + i--; + earliestProfile = profilesByDepartureStop[i]; + } + profilesByDepartureStop[i + 1] = newProfile; } } } diff --git a/src/planner/public-transport/PublicTransportPlannerEAT.ts b/src/planner/public-transport/PublicTransportPlannerEAT.ts deleted file mode 100644 index 32214c39..00000000 --- a/src/planner/public-transport/PublicTransportPlannerEAT.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { injectable } from "inversify"; -import IPath from "../../interfaces/IPath"; -import IResolvedQuery from "../../query-runner/IResolvedQuery"; -import IPublicTransportPlanner from "./IPublicTransportPlanner"; - -@injectable() -export default class PublicTransportPlannerEAT implements IPublicTransportPlanner { - public plan: (query: IResolvedQuery) => Promise; - -} diff --git a/src/planner/road/RoadPlannerBirdsEye.test.ts b/src/planner/road/RoadPlannerBirdsEye.test.ts index 5848ecb6..7f6201a2 100644 --- a/src/planner/road/RoadPlannerBirdsEye.test.ts +++ b/src/planner/road/RoadPlannerBirdsEye.test.ts @@ -1,39 +1,35 @@ import "jest"; -import Context from "../../Context"; -import StopsFetcherNMBS from "../../fetcher/stops/StopsFetcherNMBS"; +import LDFetch from "ldfetch"; +import StopsFetcherLDFetch from "../../fetcher/stops/ld-fetch/StopsFetcherLDFetch"; import IPath from "../../interfaces/IPath"; import LocationResolverDefault from "../../query-runner/LocationResolverDefault"; -import TYPES from "../../types"; +import Iterators from "../../util/Iterators"; import IRoadPlanner from "./IRoadPlanner"; import RoadPlannerBirdsEye from "./RoadPlannerBirdsEye"; -const dummyContext = { - getContainer() { - return { - getAll(type) { - if (type === TYPES.StopsFetcher) { - return [new StopsFetcherNMBS()]; - } - }, - }; - }, -}; - +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); const planner: IRoadPlanner = new RoadPlannerBirdsEye(); -const locationResolver = new LocationResolverDefault(dummyContext as Context); + +const stopsFetcher = new StopsFetcherLDFetch(ldFetch); +stopsFetcher.setPrefix("http://irail.be/stations/NMBS/"); +stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); + +const locationResolver = new LocationResolverDefault(stopsFetcher); test("[RoadPlannerBirdsEye] distance between stops", async () => { - const kortrijkLocation = await locationResolver.resolve({id: "http://irail.be/stations/NMBS/008896008"}); - const ghentLocation = await locationResolver.resolve({id: "http://irail.be/stations/NMBS/008892007"}); + const kortrijkLocation = await locationResolver.resolve({ id: "http://irail.be/stations/NMBS/008896008" }); + const ghentLocation = await locationResolver.resolve({ id: "http://irail.be/stations/NMBS/008892007" }); - const result: IPath[] = await planner.plan({ + const iterator = await planner.plan({ from: [kortrijkLocation], // Kortrijk to: [ghentLocation], // Ghent-Sint-Pieters, minimumWalkingSpeed: 3, maximumWalkingSpeed: 6, }); + const result: IPath[] = await Iterators.toArray(iterator); + expect(result).toHaveLength(1); // todo test result[0].steps diff --git a/src/planner/road/RoadPlannerBirdsEye.ts b/src/planner/road/RoadPlannerBirdsEye.ts index 380568a8..06cc4f09 100644 --- a/src/planner/road/RoadPlannerBirdsEye.ts +++ b/src/planner/road/RoadPlannerBirdsEye.ts @@ -1,15 +1,19 @@ -import haversine from "haversine"; +import { ArrayIterator, AsyncIterator } from "asynciterator"; import { injectable } from "inversify"; import ILocation from "../../interfaces/ILocation"; import IPath from "../../interfaces/IPath"; import IProbabilisticValue from "../../interfaces/IProbabilisticValue"; +import { DurationMs, SpeedkmH } from "../../interfaces/units"; import IResolvedQuery from "../../query-runner/IResolvedQuery"; +import TravelMode from "../../TravelMode"; +import Geo from "../../util/Geo"; +import Units from "../../util/Units"; import IRoadPlanner from "./IRoadPlanner"; @injectable() export default class RoadPlannerBirdsEye implements IRoadPlanner { - public async plan(query: IResolvedQuery): Promise { + public async plan(query: IResolvedQuery): Promise> { const { from: fromLocations, to: toLocations, minimumWalkingSpeed, maximumWalkingSpeed} = query; const paths = []; @@ -23,21 +27,21 @@ export default class RoadPlannerBirdsEye implements IRoadPlanner { } } - return paths; + return new ArrayIterator(paths); } private getPathBetweenLocations( from: ILocation, to: ILocation, - minWalkingSpeed: number, - maxWalkingSpeed: number, + minWalkingSpeed: SpeedkmH, + maxWalkingSpeed: SpeedkmH, ): IPath { - const distance = this.getDistanceBetweenLocations(from, to); - const minDuration = distance / maxWalkingSpeed; - const maxDuration = distance / minWalkingSpeed; + const distance = Geo.getDistanceBetweenLocations(from, to); + const minDuration = Units.toDuration(distance, maxWalkingSpeed); + const maxDuration = Units.toDuration(distance, minWalkingSpeed); - const duration: IProbabilisticValue = { + const duration: IProbabilisticValue = { minimum: minDuration, maximum: maxDuration, average: (minDuration + maxDuration) / 2, @@ -49,25 +53,8 @@ export default class RoadPlannerBirdsEye implements IRoadPlanner { stopLocation: to, duration, distance, + travelMode: TravelMode.Walking, }], }; } - - private getDistanceBetweenLocations(from: ILocation, to: ILocation): number { - const { longitude: depLongitude, latitude: depLatitude } = from; - const { longitude: arrLongitude, latitude: arrLatitude } = to; - - if (depLongitude === undefined || depLatitude === undefined || - arrLongitude === undefined || arrLatitude === undefined) { - return Number.POSITIVE_INFINITY; - } - - return haversine({ - latitude: depLatitude, - longitude: depLongitude, - }, { - latitude: arrLatitude, - longitude: arrLongitude, - }); - } } diff --git a/src/planner/stops/IReachableStopsFinder.ts b/src/planner/stops/IReachableStopsFinder.ts new file mode 100644 index 00000000..5ce8deb7 --- /dev/null +++ b/src/planner/stops/IReachableStopsFinder.ts @@ -0,0 +1,17 @@ +import IStop from "../../fetcher/stops/IStop"; +import { DurationMs, SpeedkmH } from "../../interfaces/units"; +import ReachableStopsFinderMode from "./ReachableStopsFinderMode"; + +export default interface IReachableStopsFinder { + findReachableStops: ( + sourceOrTargetStop: IStop, + mode: ReachableStopsFinderMode, + maximumDuration: DurationMs, + minimumSpeed: SpeedkmH, + ) => Promise; +} + +export interface IReachableStop { + stop: IStop; + duration: DurationMs; +} diff --git a/src/planner/stops/ReachableStopsFinderBirdsEye.test.ts b/src/planner/stops/ReachableStopsFinderBirdsEye.test.ts new file mode 100644 index 00000000..c503f602 --- /dev/null +++ b/src/planner/stops/ReachableStopsFinderBirdsEye.test.ts @@ -0,0 +1,41 @@ +import "jest"; +import LDFetch from "ldfetch"; +import StopsFetcherLDFetch from "../../fetcher/stops/ld-fetch/StopsFetcherLDFetch"; +import Units from "../../util/Units"; +import ReachableStopsFinderBirdsEye from "./ReachableStopsFinderBirdsEye"; +import ReachableStopsFinderMode from "./ReachableStopsFinderMode"; + +const DE_LIJN_STOPS_URLS = [ + "http://openplanner.ilabt.imec.be/delijn/Antwerpen/stops", + "http://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/stops", + "http://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/stops", + "http://openplanner.ilabt.imec.be/delijn/Vlaams-Brabant/stops", + "http://openplanner.ilabt.imec.be/delijn/Limburg/stops", +]; + +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + +const stopsFetcher = new StopsFetcherLDFetch(ldFetch); +stopsFetcher.setPrefix("https://data.delijn.be/stops/"); +stopsFetcher.setAccessUrl(DE_LIJN_STOPS_URLS[2]); + +const reachableStopsFinder = new ReachableStopsFinderBirdsEye(stopsFetcher); + +test("[ReachableStopsFinderBirdsEye] reachable stops", async () => { + jest.setTimeout(15000); + + // Vierweg in West-Vlaanderen + const sourceStop = await stopsFetcher.getStopById("https://data.delijn.be/stops/590009"); + + expect(sourceStop).toBeDefined(); + + // Get reachable stops in 1 km (.25h at 4km/h) + const reachableStops = await reachableStopsFinder.findReachableStops( + sourceStop, + ReachableStopsFinderMode.Source, + Units.fromHours(0.25), + 4, + ); + + expect(reachableStops.length).toBeGreaterThan(1); +}); diff --git a/src/planner/stops/ReachableStopsFinderBirdsEye.ts b/src/planner/stops/ReachableStopsFinderBirdsEye.ts new file mode 100644 index 00000000..defb77a9 --- /dev/null +++ b/src/planner/stops/ReachableStopsFinderBirdsEye.ts @@ -0,0 +1,45 @@ +import { inject, injectable } from "inversify"; +import IStop from "../../fetcher/stops/IStop"; +import IStopsProvider from "../../fetcher/stops/IStopsProvider"; +import { DurationMs, SpeedkmH } from "../../interfaces/units"; +import TYPES from "../../types"; +import Geo from "../../util/Geo"; +import Units from "../../util/Units"; +import IReachableStopsFinder, { IReachableStop } from "./IReachableStopsFinder"; +import ReachableStopsFinderMode from "./ReachableStopsFinderMode"; + +@injectable() +export default class ReachableStopsFinderBirdsEye implements IReachableStopsFinder { + private readonly stopsProvider: IStopsProvider; + + constructor( + @inject(TYPES.StopsProvider) stopsProvider: IStopsProvider, + ) { + this.stopsProvider = stopsProvider; + } + + public async findReachableStops( + sourceOrTargetStop: IStop, + mode: ReachableStopsFinderMode, + maximumDuration: DurationMs, + minimumSpeed: SpeedkmH, + ): Promise { + + // Mode can be ignored since birds eye view distance is identical + + const allStops = await this.stopsProvider.getAllStops(); + + return allStops.map((possibleTarget: IStop): IReachableStop => { + if (possibleTarget.id === sourceOrTargetStop.id) { + return {stop: sourceOrTargetStop, duration: 0}; + } + + const distance = Geo.getDistanceBetweenStops(sourceOrTargetStop, possibleTarget); + const duration = Units.toDuration(distance, minimumSpeed); + + if (duration <= maximumDuration) { + return {stop: possibleTarget, duration}; + } + }).filter((reachableStop) => !!reachableStop); + } +} diff --git a/src/planner/stops/ReachableStopsFinderBirdsEyeCached.ts b/src/planner/stops/ReachableStopsFinderBirdsEyeCached.ts new file mode 100644 index 00000000..cc290197 --- /dev/null +++ b/src/planner/stops/ReachableStopsFinderBirdsEyeCached.ts @@ -0,0 +1,44 @@ +import { inject, injectable } from "inversify"; +import IStop from "../../fetcher/stops/IStop"; +import IStopsProvider from "../../fetcher/stops/IStopsProvider"; +import { DurationMs, SpeedkmH } from "../../interfaces/units"; +import TYPES from "../../types"; +import IReachableStopsFinder, { IReachableStop } from "./IReachableStopsFinder"; +import ReachableStopsFinderBirdsEye from "./ReachableStopsFinderBirdsEye"; +import ReachableStopsFinderMode from "./ReachableStopsFinderMode"; + +@injectable() +export default class ReachableStopsFinderBirdsEyeCached implements IReachableStopsFinder { + private readonly reachableStopsFinder: ReachableStopsFinderBirdsEye; + private readonly reachableStopsCache: {[cacheKey: string]: IReachableStop[]}; + + constructor( + @inject(TYPES.StopsProvider) stopsProvider: IStopsProvider, + ) { + this.reachableStopsFinder = new ReachableStopsFinderBirdsEye(stopsProvider); + this.reachableStopsCache = {}; + } + + public async findReachableStops( + sourceOrTargetStop: IStop, + mode: ReachableStopsFinderMode, + maximumDuration: DurationMs, + minimumSpeed: SpeedkmH, + ): Promise { + + // Mode can be ignored since birds eye view distance is identical + + const cacheKey = `${sourceOrTargetStop.id} ${maximumDuration} ${minimumSpeed}`; + const cacheItem = this.reachableStopsCache[cacheKey]; + + if (cacheItem) { + return cacheItem; + } + + const reachableStops = await this.reachableStopsFinder + .findReachableStops(sourceOrTargetStop, mode, maximumDuration, minimumSpeed); + + this.reachableStopsCache[cacheKey] = reachableStops; + return reachableStops; + } +} diff --git a/src/planner/stops/ReachableStopsFinderMode.ts b/src/planner/stops/ReachableStopsFinderMode.ts new file mode 100644 index 00000000..0558a534 --- /dev/null +++ b/src/planner/stops/ReachableStopsFinderMode.ts @@ -0,0 +1,6 @@ +enum ReachableStopsFinderMode { + Source = "source", + Target = "target", +} + +export default ReachableStopsFinderMode; diff --git a/src/planner/stops/ReachableStopsFinderRoadPlanner.test.ts b/src/planner/stops/ReachableStopsFinderRoadPlanner.test.ts new file mode 100644 index 00000000..9013d2e5 --- /dev/null +++ b/src/planner/stops/ReachableStopsFinderRoadPlanner.test.ts @@ -0,0 +1,33 @@ +import "jest"; +import LDFetch from "ldfetch"; +import StopsFetcherLDFetch from "../../fetcher/stops/ld-fetch/StopsFetcherLDFetch"; +import Units from "../../util/Units"; +import RoadPlannerBirdsEye from "../road/RoadPlannerBirdsEye"; +import ReachableStopsFinderMode from "./ReachableStopsFinderMode"; +import ReachableStopsFinderRoadPlanner from "./ReachableStopsFinderRoadPlanner"; + +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + +const stopsFetcher = new StopsFetcherLDFetch(ldFetch); +stopsFetcher.setPrefix("http://irail.be/stations/NMBS/"); +stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); + +const roadPlanner = new RoadPlannerBirdsEye(); +const reachableStopsFinder = new ReachableStopsFinderRoadPlanner(stopsFetcher, roadPlanner); + +test("[ReachableStopsFinderRoadPlanner] reachable stops", async () => { + + const sourceStop = await stopsFetcher.getStopById("http://irail.be/stations/NMBS/008896008"); + + expect(sourceStop).toBeDefined(); + + // Get reachable stops in 50 km (10h at 5km/h) + const reachableStops = await reachableStopsFinder.findReachableStops( + sourceStop, + ReachableStopsFinderMode.Source, + Units.fromHours(1), + 5, + ); + + expect(reachableStops.length).toBeGreaterThan(1); +}); diff --git a/src/planner/stops/ReachableStopsFinderRoadPlanner.ts b/src/planner/stops/ReachableStopsFinderRoadPlanner.ts new file mode 100644 index 00000000..9c9206dc --- /dev/null +++ b/src/planner/stops/ReachableStopsFinderRoadPlanner.ts @@ -0,0 +1,77 @@ +import { AsyncIterator } from "asynciterator"; +import { inject, injectable } from "inversify"; +import IStop from "../../fetcher/stops/IStop"; +import IStopsProvider from "../../fetcher/stops/IStopsProvider"; +import ILocation from "../../interfaces/ILocation"; +import IPath from "../../interfaces/IPath"; +import { DurationMs, SpeedkmH } from "../../interfaces/units"; +import IResolvedQuery from "../../query-runner/IResolvedQuery"; +import TYPES from "../../types"; +import Iterators from "../../util/Iterators"; +import IRoadPlanner from "../road/IRoadPlanner"; +import IReachableStopsFinder, { IReachableStop } from "./IReachableStopsFinder"; +import ReachableStopsFinderMode from "./ReachableStopsFinderMode"; + +@injectable() +export default class ReachableStopsFinderRoadPlanner implements IReachableStopsFinder { + private readonly stopsProvider: IStopsProvider; + private readonly roadPlanner: IRoadPlanner; + + constructor( + @inject(TYPES.StopsProvider) stopsProvider: IStopsProvider, + @inject(TYPES.RoadPlanner) roadPlanner: IRoadPlanner, + ) { + this.stopsProvider = stopsProvider; + this.roadPlanner = roadPlanner; + } + + public async findReachableStops( + sourceOrTargetStop: IStop, + mode: ReachableStopsFinderMode, + maximumDuration: DurationMs, + minimumSpeed: SpeedkmH, + ): Promise { + + const minimumDepartureTime = new Date(); + const maximumArrivalTime = new Date(minimumDepartureTime.getTime() + maximumDuration); + + const baseProp = mode === ReachableStopsFinderMode.Target ? "to" : "from"; + const otherProp = mode === ReachableStopsFinderMode.Target ? "from" : "to"; + + const baseQuery: IResolvedQuery = { + [baseProp]: [sourceOrTargetStop as ILocation], + minimumDepartureTime, + maximumArrivalTime, + minimumWalkingSpeed: minimumSpeed, + }; + + const allStops = await this.stopsProvider.getAllStops(); + const reachableStops: IReachableStop[] = [{stop: sourceOrTargetStop, duration: 0}]; + + await Promise.all(allStops.map(async (possibleTarget: IStop) => { + if (possibleTarget.id !== sourceOrTargetStop.id) { + + const query = Object.assign({}, baseQuery, { + [otherProp]: [possibleTarget as ILocation], + }); + + const pathIterator = await this.roadPlanner.plan(query); + + const durationIterator: AsyncIterator = pathIterator.map((path: IPath) => + // Minimum speed is passed so sum max duration over all steps + path.steps.reduce((totalDuration: DurationMs, step) => totalDuration + step.duration.maximum, 0), + ); + + const sufficientlyShortDuration = await Iterators + .find(durationIterator, (duration: DurationMs) => duration < maximumDuration); + + if (sufficientlyShortDuration) { + reachableStops.push({stop: possibleTarget, duration: sufficientlyShortDuration}); + } + } + + })); + + return reachableStops; + } +} diff --git a/src/planner/stops/ReachableStopsFinderRoadPlannerCached.ts b/src/planner/stops/ReachableStopsFinderRoadPlannerCached.ts new file mode 100644 index 00000000..9a475f07 --- /dev/null +++ b/src/planner/stops/ReachableStopsFinderRoadPlannerCached.ts @@ -0,0 +1,44 @@ +import { inject, injectable } from "inversify"; +import IStop from "../../fetcher/stops/IStop"; +import IStopsProvider from "../../fetcher/stops/IStopsProvider"; +import { DurationMs, SpeedkmH } from "../../interfaces/units"; +import TYPES from "../../types"; +import IRoadPlanner from "../road/IRoadPlanner"; +import IReachableStopsFinder, { IReachableStop } from "./IReachableStopsFinder"; +import ReachableStopsFinderMode from "./ReachableStopsFinderMode"; +import ReachableStopsFinderRoadPlanner from "./ReachableStopsFinderRoadPlanner"; + +@injectable() +export default class ReachableStopsFinderRoadPlannerCached implements IReachableStopsFinder { + private readonly reachableStopsFinder: ReachableStopsFinderRoadPlanner; + private readonly reachableStopsCache: {[cacheKey: string]: IReachableStop[]}; + + constructor( + @inject(TYPES.StopsProvider) stopsProvider: IStopsProvider, + @inject(TYPES.RoadPlanner) roadPlanner: IRoadPlanner, + ) { + this.reachableStopsFinder = new ReachableStopsFinderRoadPlanner(stopsProvider, roadPlanner); + this.reachableStopsCache = {}; + } + + public async findReachableStops( + sourceOrTargetStop: IStop, + mode: ReachableStopsFinderMode, + maximumDuration: DurationMs, + minimumSpeed: SpeedkmH, + ): Promise { + + const cacheKey = `${sourceOrTargetStop.id} ${mode} ${maximumDuration} ${minimumSpeed}`; + const cacheItem = this.reachableStopsCache[cacheKey]; + + if (cacheItem) { + return cacheItem; + } + + const reachableStops = await this.reachableStopsFinder + .findReachableStops(sourceOrTargetStop, mode, maximumDuration, minimumSpeed); + + this.reachableStopsCache[cacheKey] = reachableStops; + return reachableStops; + } +} diff --git a/src/planner/stops/ReachableStopsSearchPhase.ts b/src/planner/stops/ReachableStopsSearchPhase.ts new file mode 100644 index 00000000..96dac2be --- /dev/null +++ b/src/planner/stops/ReachableStopsSearchPhase.ts @@ -0,0 +1,13 @@ +/** + * Signifies different phases at which reachable stops can be searched for + * Classes that use [[IReachableStopsFinder]] implementations can use these to tag different dependencies + * This is especially useful when the class could potentially use different implementations of + * the same [[IReachableStopsFinder]] interface at each phase + */ +enum ReachableStopsSearchPhase { + Initial = "reachableStopsSearchInitial", + Transfer = "reachableStopsSearchTransfer", + Final = "reachableStopsSearchFinal", +} + +export default ReachableStopsSearchPhase; diff --git a/src/query-runner/ILocationResolver.ts b/src/query-runner/ILocationResolver.ts index a2221930..a4f4f93c 100644 --- a/src/query-runner/ILocationResolver.ts +++ b/src/query-runner/ILocationResolver.ts @@ -1,5 +1,6 @@ +import IStop from "../fetcher/stops/IStop"; import ILocation from "../interfaces/ILocation"; export default interface ILocationResolver { - resolve: (location: ILocation | string) => Promise; + resolve: (location: ILocation | IStop | string) => Promise; } diff --git a/src/query-runner/IQueryRunner.ts b/src/query-runner/IQueryRunner.ts index f6a51529..6103a303 100644 --- a/src/query-runner/IQueryRunner.ts +++ b/src/query-runner/IQueryRunner.ts @@ -1,7 +1,8 @@ +import { AsyncIterator } from "asynciterator"; +import IPath from "../interfaces/IPath"; import IQuery from "../interfaces/IQuery"; -import IQueryResult from "../interfaces/IQueryResult"; export default interface IQueryRunner { - run(query: IQuery): Promise; + run(query: IQuery): Promise>; } diff --git a/src/query-runner/IResolvedQuery.ts b/src/query-runner/IResolvedQuery.ts index 12b6f72a..db2f1710 100644 --- a/src/query-runner/IResolvedQuery.ts +++ b/src/query-runner/IResolvedQuery.ts @@ -1,4 +1,5 @@ import ILocation from "../interfaces/ILocation"; +import { DurationMs, SpeedkmH } from "../interfaces/units"; export default interface IResolvedQuery { from?: ILocation[]; @@ -7,6 +8,8 @@ export default interface IResolvedQuery { maximumArrivalTime?: Date; roadOnly?: boolean; publicTransportOnly?: boolean; - minimumWalkingSpeed?: number; - maximumWalkingSpeed?: number; + minimumWalkingSpeed?: SpeedkmH; + maximumWalkingSpeed?: SpeedkmH; + maximumTransferDuration?: DurationMs; + maximumTransfers?: number; } diff --git a/src/query-runner/LocationResolverDefault.test.ts b/src/query-runner/LocationResolverDefault.test.ts index e8507c4b..5f3cd9a8 100644 --- a/src/query-runner/LocationResolverDefault.test.ts +++ b/src/query-runner/LocationResolverDefault.test.ts @@ -1,22 +1,15 @@ import "jest"; -import Context from "../Context"; -import StopsFetcherNMBS from "../fetcher/stops/StopsFetcherNMBS"; -import TYPES from "../types"; +import LDFetch from "ldfetch"; +import StopsFetcherLDFetch from "../fetcher/stops/ld-fetch/StopsFetcherLDFetch"; import LocationResolverDefault from "./LocationResolverDefault"; -const dummyContext = { - getContainer() { - return { - getAll(type) { - if (type === TYPES.StopsFetcher) { - return [new StopsFetcherNMBS()]; - } - }, - }; - }, -}; - -const locationResolver = new LocationResolverDefault(dummyContext as Context); +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + +const stopsFetcher = new StopsFetcherLDFetch(ldFetch); +stopsFetcher.setPrefix("http://irail.be/stations/NMBS/"); +stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); + +const locationResolver = new LocationResolverDefault(stopsFetcher); test("[LocationResolverDefault] Input {id: 'http://...'}", async () => { diff --git a/src/query-runner/LocationResolverDefault.ts b/src/query-runner/LocationResolverDefault.ts index 2fae1390..8283d19e 100644 --- a/src/query-runner/LocationResolverDefault.ts +++ b/src/query-runner/LocationResolverDefault.ts @@ -1,23 +1,21 @@ import { inject, injectable } from "inversify"; -import Context from "../Context"; import IStop from "../fetcher/stops/IStop"; -import IStopsFetcher from "../fetcher/stops/IStopsFetcher"; +import IStopsProvider from "../fetcher/stops/IStopsProvider"; import ILocation from "../interfaces/ILocation"; import TYPES from "../types"; import ILocationResolver from "./ILocationResolver"; @injectable() export default class LocationResolverDefault implements ILocationResolver { - private readonly stopsFetchers: IStopsFetcher[]; + private readonly stopsProvider: IStopsProvider; constructor( - @inject(TYPES.Context) context: Context, + @inject(TYPES.StopsProvider) stopsProvider: IStopsProvider, ) { - this.stopsFetchers = context.getContainer() - .getAll(TYPES.StopsFetcher); + this.stopsProvider = stopsProvider; } - public async resolve(input: ILocation | string): Promise { + public async resolve(input: ILocation | IStop | string): Promise { if (typeof input === "string") { @@ -46,35 +44,20 @@ export default class LocationResolverDefault implements ILocationResolver { } private async resolveById(id: string): Promise { - const fetcher = this.determineStopFetcher(id); - - if (fetcher) { - const stop: IStop = await fetcher.getStopById(id); - - if (stop) { - return { - id, - latitude: stop.latitude, - longitude: stop.longitude, - }; - } + const stop: IStop = await this.stopsProvider.getStopById(id); + + if (stop) { + return { + id, + name: stop.name, + latitude: stop.latitude, + longitude: stop.longitude, + }; } throw new Error(`No fetcher for id ${id}`); } - private determineStopFetcher(id: string): IStopsFetcher { - if (!this.stopsFetchers || !this.stopsFetchers.length) { - return null; - } - - for (const fetcher of this.stopsFetchers) { - if (id.indexOf(fetcher.prefix) === 0) { - return fetcher; - } - } - } - private isId(testString: string): boolean { return testString.indexOf("http://") === 0 || testString.indexOf("https://") === 0; } diff --git a/src/query-runner/QueryRunnerDefault.ts b/src/query-runner/QueryRunnerDefault.ts index e009db48..dbd78739 100644 --- a/src/query-runner/QueryRunnerDefault.ts +++ b/src/query-runner/QueryRunnerDefault.ts @@ -1,10 +1,10 @@ +import { AsyncIterator } from "asynciterator"; import { inject, injectable } from "inversify"; +import Defaults from "../Defaults"; import ILocation from "../interfaces/ILocation"; import IPath from "../interfaces/IPath"; import IQuery from "../interfaces/IQuery"; -import IQueryResult from "../interfaces/IQueryResult"; import IPublicTransportPlanner from "../planner/public-transport/IPublicTransportPlanner"; -import IRoadPlanner from "../planner/road/IRoadPlanner"; import TYPES from "../types"; import ILocationResolver from "./ILocationResolver"; import IQueryRunner from "./IQueryRunner"; @@ -14,30 +14,24 @@ import IResolvedQuery from "./IResolvedQuery"; export default class QueryRunnerDefault implements IQueryRunner { private locationResolver: ILocationResolver; private publicTransportPlanner: IPublicTransportPlanner; - private roadPlanner: IRoadPlanner; constructor( @inject(TYPES.LocationResolver) locationResolver: ILocationResolver, @inject(TYPES.PublicTransportPlanner) publicTransportPlanner: IPublicTransportPlanner, - @inject(TYPES.RoadPlanner) roadPlanner: IRoadPlanner, ) { this.locationResolver = locationResolver; this.publicTransportPlanner = publicTransportPlanner; - this.roadPlanner = roadPlanner; } - public async run(query: IQuery): Promise { + public async run(query: IQuery): Promise> { const resolvedQuery: IResolvedQuery = await this.resolveQuery(query); - if (resolvedQuery.roadOnly) { - return this.runRoadOnlyQuery(resolvedQuery); - } - if (resolvedQuery.publicTransportOnly) { - return this.runPublicTransportOnlyQuery(resolvedQuery); - } + return this.publicTransportPlanner.plan(resolvedQuery); - return Promise.reject("Query not supported"); + } else { + return Promise.reject("Query not supported"); + } } private async resolveEndpoint(endpoint: string | string[] | ILocation | ILocation[]): Promise { @@ -56,26 +50,38 @@ export default class QueryRunnerDefault implements IQueryRunner { } private async resolveQuery(query: IQuery): Promise { - const { from, to, minimumWalkingSpeed, maximumWalkingSpeed, walkingSpeed, ...other} = query; + // tslint:disable:trailing-comma + const { + from, to, + minimumWalkingSpeed, maximumWalkingSpeed, walkingSpeed, + maximumTransferDuration, maximumTransfers, + minimumDepartureTime, maximumArrivalTime, + ...other + } = query; + // tslint:enable:trailing-comma + const resolvedQuery: IResolvedQuery = Object.assign({}, other); - resolvedQuery.from = await this.resolveEndpoint(from); - resolvedQuery.to = await this.resolveEndpoint(to); - resolvedQuery.minimumWalkingSpeed = minimumWalkingSpeed || walkingSpeed || maximumWalkingSpeed; - resolvedQuery.maximumWalkingSpeed = maximumWalkingSpeed || walkingSpeed || minimumWalkingSpeed; + resolvedQuery.minimumDepartureTime = minimumDepartureTime || new Date(); - return resolvedQuery; - } + if (maximumArrivalTime) { + resolvedQuery.maximumArrivalTime = maximumArrivalTime; - private async runRoadOnlyQuery(query: IResolvedQuery): Promise { + } else { + const newMaximumArrivalTime = new Date(resolvedQuery.minimumDepartureTime); + newMaximumArrivalTime.setHours(newMaximumArrivalTime.getHours() + 2); - const result: IPath[] = await this.roadPlanner.plan(query); - return Promise.resolve({ paths: result }); - } + resolvedQuery.maximumArrivalTime = newMaximumArrivalTime; + } - private async runPublicTransportOnlyQuery(query: IResolvedQuery): Promise { + resolvedQuery.from = await this.resolveEndpoint(from); + resolvedQuery.to = await this.resolveEndpoint(to); + resolvedQuery.minimumWalkingSpeed = minimumWalkingSpeed || walkingSpeed || Defaults.defaultMinimumWalkingSpeed; + resolvedQuery.maximumWalkingSpeed = maximumWalkingSpeed || walkingSpeed || Defaults.defaultMaximumWalkingSpeed; - const result: IPath[] = await this.publicTransportPlanner.plan(query); - return Promise.resolve({ paths: result }); + resolvedQuery.maximumTransferDuration = maximumTransferDuration || Defaults.defaultMaximumTransferDuration; + resolvedQuery.maximumTransfers = maximumTransfers || Defaults.defaultMaximumTransfers; + + return resolvedQuery; } } diff --git a/src/query-runner/exponential/ExponentialQueryIterator.ts b/src/query-runner/exponential/ExponentialQueryIterator.ts new file mode 100644 index 00000000..5f874b8f --- /dev/null +++ b/src/query-runner/exponential/ExponentialQueryIterator.ts @@ -0,0 +1,32 @@ +import { AsyncIterator } from "asynciterator"; +import { DurationMs } from "../../interfaces/units"; +import IResolvedQuery from "../IResolvedQuery"; + +// Inspired by IntegerIterator +export default class ExponentialQueryIterator extends AsyncIterator { + private readonly baseQuery: IResolvedQuery; + private timespan: DurationMs; + + constructor(baseQuery: IResolvedQuery, initialTimespan: DurationMs) { + super(); + + this.baseQuery = baseQuery; + this.timespan = initialTimespan; + + this.readable = true; + } + + public read(): IResolvedQuery { + if (this.closed) { + return null; + } + + const {minimumDepartureTime} = this.baseQuery; + const maximumArrivalTime = new Date(minimumDepartureTime.getTime() + this.timespan); + + this.timespan *= 2; + + return Object.assign({}, this.baseQuery, {maximumArrivalTime}); + } + +} diff --git a/src/query-runner/exponential/FilterUniqueIterator.ts b/src/query-runner/exponential/FilterUniqueIterator.ts new file mode 100644 index 00000000..d937d256 --- /dev/null +++ b/src/query-runner/exponential/FilterUniqueIterator.ts @@ -0,0 +1,26 @@ +import { AsyncIterator, SimpleTransformIterator } from "asynciterator"; +import IPath from "../../interfaces/IPath"; +import Path from "../../planner/Path"; + +export default class FilterUniqueIterator extends SimpleTransformIterator { + + private store: Path[]; + + constructor(source: AsyncIterator) { + super(source); + + this.store = []; + } + + public _filter(path: IPath): boolean { + + const isUnique = !this.store + .some((storedPath: Path) => storedPath.equals(path)); + + if (isUnique) { + this.store.push(path as Path); + } + + return isUnique; + } +} diff --git a/src/query-runner/exponential/QueryRunnerExponential.ts b/src/query-runner/exponential/QueryRunnerExponential.ts new file mode 100644 index 00000000..d5e2f3f2 --- /dev/null +++ b/src/query-runner/exponential/QueryRunnerExponential.ts @@ -0,0 +1,97 @@ +import { AsyncIterator } from "asynciterator"; +import { inject, injectable } from "inversify"; +import Context from "../../Context"; +import Defaults from "../../Defaults"; +import ILocation from "../../interfaces/ILocation"; +import IPath from "../../interfaces/IPath"; +import IQuery from "../../interfaces/IQuery"; +import IPublicTransportPlanner from "../../planner/public-transport/IPublicTransportPlanner"; +import TYPES from "../../types"; +import ILocationResolver from "../ILocationResolver"; +import IQueryRunner from "../IQueryRunner"; +import IResolvedQuery from "../IResolvedQuery"; +import ExponentialQueryIterator from "./ExponentialQueryIterator"; +import FilterUniqueIterator from "./FilterUniqueIterator"; +import SubqueryIterator from "./SubqueryIterator"; + +@injectable() +export default class QueryRunnerExponential implements IQueryRunner { + public private; + private locationResolver: ILocationResolver; + private publicTransportPlanner: IPublicTransportPlanner; + + private context: Context; + + constructor( + @inject(TYPES.Context) context: Context, + @inject(TYPES.LocationResolver) locationResolver: ILocationResolver, + @inject(TYPES.PublicTransportPlanner) publicTransportPlanner: IPublicTransportPlanner, + ) { + this.locationResolver = locationResolver; + this.publicTransportPlanner = publicTransportPlanner; + this.context = context; + } + + public async run(query: IQuery): Promise> { + const baseQuery: IResolvedQuery = await this.resolveBaseQuery(query); + + if (baseQuery.publicTransportOnly) { + + const queryIterator = new ExponentialQueryIterator(baseQuery, 15 * 60 * 1000); + const subqueryIterator = new SubqueryIterator(queryIterator, this.runSubquery.bind(this)); + + return new FilterUniqueIterator(subqueryIterator); + + } else { + return Promise.reject("Query not supported"); + } + } + + private async runSubquery(query: IResolvedQuery): Promise> { + // TODO investigate publicTransportPlanner + const planner = this.context.getContainer().get(TYPES.PublicTransportPlanner); + + return planner.plan(query); + } + + private async resolveEndpoint(endpoint: string | string[] | ILocation | ILocation[]): Promise { + + if (Array.isArray(endpoint)) { + const promises = (endpoint as Array) + .map((singleEndpoint: string | ILocation) => + this.locationResolver.resolve(singleEndpoint), + ); + + return await Promise.all(promises); + + } else { + return [await this.locationResolver.resolve(endpoint)]; + } + } + + private async resolveBaseQuery(query: IQuery): Promise { + // tslint:disable:trailing-comma + const { + from, to, + minimumWalkingSpeed, maximumWalkingSpeed, walkingSpeed, + maximumTransferDuration, maximumTransfers, + minimumDepartureTime, + ...other + } = query; + // tslint:enable:trailing-comma + + const resolvedQuery: IResolvedQuery = Object.assign({}, other); + + resolvedQuery.minimumDepartureTime = minimumDepartureTime || new Date(); + + resolvedQuery.from = await this.resolveEndpoint(from); + resolvedQuery.to = await this.resolveEndpoint(to); + resolvedQuery.minimumWalkingSpeed = minimumWalkingSpeed || walkingSpeed || Defaults.defaultMinimumWalkingSpeed; + resolvedQuery.maximumWalkingSpeed = maximumWalkingSpeed || walkingSpeed || Defaults.defaultMaximumWalkingSpeed; + + resolvedQuery.maximumTransferDuration = maximumTransferDuration || Defaults.defaultMaximumTransferDuration; + resolvedQuery.maximumTransfers = maximumTransfers || Defaults.defaultMaximumTransfers; + + return resolvedQuery; + } +} diff --git a/src/query-runner/exponential/SubqueryIterator.test.ts b/src/query-runner/exponential/SubqueryIterator.test.ts new file mode 100644 index 00000000..4d6632b5 --- /dev/null +++ b/src/query-runner/exponential/SubqueryIterator.test.ts @@ -0,0 +1,28 @@ +import { ArrayIterator } from "asynciterator"; +import "jest"; +import SubqueryIterator from "./SubqueryIterator"; + +const ALPHABET = "abc"; + +const queryIterator = new ArrayIterator([1, 2, 3]); + +const subqueryIterator = new SubqueryIterator(queryIterator, (num) => { + return new Promise((resolve) => { + const array = Array(num).fill(ALPHABET[num - 1]); + + resolve(new ArrayIterator(array)); + }); +}); + +test("[SubqueryIterator]", (done) => { + + let current = 0; + const expected = ["a", "b", "b", "c", "c", "c"]; + + subqueryIterator.each((str) => { + expect(expected[current++]).toBe(str); + }); + + subqueryIterator.on("end", () => done()); + +}); diff --git a/src/query-runner/exponential/SubqueryIterator.ts b/src/query-runner/exponential/SubqueryIterator.ts new file mode 100644 index 00000000..10485a6e --- /dev/null +++ b/src/query-runner/exponential/SubqueryIterator.ts @@ -0,0 +1,94 @@ +import { AsyncIterator, BufferedIterator } from "asynciterator"; + +export default class SubqueryIterator extends BufferedIterator { + private queryIterator: AsyncIterator; + private callback: (query: Q) => Promise>; + + private currentResultIterator: AsyncIterator; + private currentResultPushed: number; + private isLastResultIterator = false; + + constructor(queryIterator: AsyncIterator, run: (query: Q) => Promise>) { + super(); + + this.queryIterator = queryIterator; + this.callback = run; + + this.queryIterator.once("end", () => { + this.isLastResultIterator = true; + }); + } + + public _read(count: number, done: () => void) { + if (!this.currentResultIterator) { + const query = this.queryIterator.read(); + + if (query) { + this.runSubquery(query, done); + + } else { + this.waitForSubquery(done); + } + + return; + } + + this.pushItemsAsync(done); + } + + private runSubquery(subquery: Q, done: () => void) { + const self = this; + + this.callback(subquery) + .then((resultIterator: AsyncIterator) => { + self.currentResultIterator = resultIterator; + self.currentResultPushed = 0; + + self.currentResultIterator.once("end", () => { + delete self.currentResultIterator; + + // Close if last iterator + if (self.isLastResultIterator) { + self.close(); + } + + // Iterator was empty + if (self.currentResultPushed === 0) { + self._read(null, done); + } + }); + + this.pushItemsAsync(done); + }); + } + + private waitForSubquery(done: () => void) { + this.queryIterator.once("readable", () => { + const query = this.queryIterator.read(); + + this.runSubquery(query, done); + }); + } + + private pushItemsAsync(done) { + this.currentResultIterator.on("readable", () => { + this.pushItemsSync(); + done(); + }); + } + + private pushItemsSync(): boolean { + let item = this.currentResultIterator.read(); + let hasPushed = false; + + while (item) { + this._push(item); + this.currentResultPushed++; + hasPushed = true; + + item = this.currentResultIterator.read(); + } + + return hasPushed; + } +} diff --git a/src/test/test-connections-iterator-2.ts b/src/test/test-connections-iterator-2.ts new file mode 100644 index 00000000..ac9a9cfb --- /dev/null +++ b/src/test/test-connections-iterator-2.ts @@ -0,0 +1,37 @@ +import LDFetch from "ldfetch"; +import ConnectionsIteratorLazy from "../fetcher/connections/ld-fetch/ConnectionsIteratorLazy"; +import TravelMode from "../TravelMode"; + +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + +const upperBoundDate = new Date(); +upperBoundDate.setHours(upperBoundDate.getHours() + 2); + +const config = { + upperBoundDate, + backward: true, +}; + +const iterator = new ConnectionsIteratorLazy( + "https://graph.irail.be/sncb/connections", + TravelMode.Train, + ldFetch, + config, + ); + +let i = 0; + +console.time("ConnectionsIterator"); + +iterator.on("readable", () => { + let connection = iterator.read(); + + while (connection && i++ < 4000) { + + connection = iterator.read(); + } + + if (i > 3999) { + console.timeEnd("ConnectionsIterator"); + } +}); diff --git a/src/test/test-connections-iterator.ts b/src/test/test-connections-iterator.ts index dec46a57..19c9f10a 100644 --- a/src/test/test-connections-iterator.ts +++ b/src/test/test-connections-iterator.ts @@ -1,16 +1,22 @@ +import LDFetch from "ldfetch"; import "reflect-metadata"; -import IConnectionsFetcher from "../fetcher/connections/IConnectionsFetcher"; -import ConnectionsFetcherDeLijn from "../fetcher/connections/ld-fetch/ConnectionsFetcherDeLijn"; -import container from "../inversify.config"; -import TYPES from "../types"; - -const fetcher = new ConnectionsFetcherDeLijn(); -// const fetcher = container.getTagged(TYPES.ConnectionsFetcher, "type", "merge"); -fetcher.setConfig({ - lowerBoundDate: new Date(), - upperBoundDate: new Date(), - backward: false, -}); +import TravelMode from "../TravelMode"; + +/* +const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); + +const upperBoundDate = new Date(); +upperBoundDate.setHours(upperBoundDate.getHours() + 2); + +const config = { + upperBoundDate, + backward: true, +}; + +const connectionsFetcher = new ConnectionsFetcherLDFetch(ldFetch); +connectionsFetcher.setTravelMode(TravelMode.Train); +connectionsFetcher.setAccessUrl("https://graph.irail.be/sncb/connections"); +connectionsFetcher.setConfig(config); // iterator.setLowerBound(new Date(2018, 10, 2, 10)); (async () => { @@ -18,14 +24,16 @@ fetcher.setConfig({ console.time("fetch"); let i = 0; + let sum = 0; - for await (const connection of fetcher) { - console.log(i++, connection["@id"], connection.departureTime); + for await (const connection of connectionsFetcher) { + sum += connection.departureDelay || 0; - if (i++ > 1000) { + if (i++ > 4000) { break; } } console.timeEnd("fetch"); })(); +*/ diff --git a/src/test/test-ldfetch.ts b/src/test/test-ldfetch.ts index 6dc09cfa..5b81f8e4 100644 --- a/src/test/test-ldfetch.ts +++ b/src/test/test-ldfetch.ts @@ -1,12 +1,12 @@ import LDFetch from "ldfetch"; -import { logTripleTable } from "../fetcher/helpers"; +import Rdf from "../util/Rdf"; const ldfetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); // ldfetch.get("http://irail.be/stations/NMBS/008896008") -ldfetch.get("https://belgium.linkedconnections.org/delijn/Oost-Vlaanderen/stops") +ldfetch.get("https://openplanner.ilabt.imec.be/delijn/Limburg/stops") .then((response) => { - logTripleTable(response.triples); + Rdf.logTripleTable(response.triples); }) .catch((reason) => { console.log(reason); diff --git a/src/types.ts b/src/types.ts index 8bbf8a4a..1874889d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,11 +1,29 @@ +import IConnectionsFetcher from "./fetcher/connections/IConnectionsFetcher"; +import IStopsFetcher from "./fetcher/stops/IStopsFetcher"; +import TravelMode from "./TravelMode"; + const TYPES = { Context: Symbol("Context"), QueryRunner: Symbol("QueryRunner"), LocationResolver: Symbol("LocationResolver"), + + ConnectionsProvider: Symbol("ConnectionsProvider"), ConnectionsFetcher: Symbol("ConnectionsFetcher"), + ConnectionsFetcherFactory: Symbol("ConnectionsFetcherFactory"), + + StopsProvider: Symbol("StopsProvider"), StopsFetcher: Symbol("StopsFetcher"), + StopsFetcherFactory: Symbol("StopsFetcherFactory"), + PublicTransportPlanner: Symbol("PublicTransportPlanner"), RoadPlanner: Symbol("RoadPlanner"), + ReachableStopsFinder: Symbol("ReachableStopsFinder"), + JourneyExtractor: Symbol("JourneyExtractor"), + LDFetch: Symbol("LDFetch"), + Catalog: Symbol("Catalog"), }; export default TYPES; + +export type StopsFetcherFactory = (prefix: string, accessUrl: string) => IStopsFetcher; +export type ConnectionsFetcherFactory = (accessUrl: string, travelMode: TravelMode) => IConnectionsFetcher; diff --git a/src/util/Geo.ts b/src/util/Geo.ts new file mode 100644 index 00000000..583cd194 --- /dev/null +++ b/src/util/Geo.ts @@ -0,0 +1,30 @@ +import haversine from "haversine"; +import IStop from "../fetcher/stops/IStop"; +import ILocation from "../interfaces/ILocation"; +import { DistanceM } from "../interfaces/units"; + +export default class Geo { + public static getDistanceBetweenLocations(start: ILocation, stop: ILocation): DistanceM { + const { longitude: depLongitude, latitude: depLatitude } = start; + const { longitude: arrLongitude, latitude: arrLatitude } = stop; + + if (depLongitude === undefined || depLatitude === undefined || + arrLongitude === undefined || arrLatitude === undefined) { + return Number.POSITIVE_INFINITY; + } + + return haversine({ + latitude: depLatitude, + longitude: depLongitude, + }, { + latitude: arrLatitude, + longitude: arrLongitude, + }, { + unit: "meter", + }); + } + + public static getDistanceBetweenStops(start: IStop, stop: IStop) { + return this.getDistanceBetweenLocations(start as ILocation, stop as ILocation); + } +} diff --git a/src/util/Iterators.ts b/src/util/Iterators.ts new file mode 100644 index 00000000..7947ea5c --- /dev/null +++ b/src/util/Iterators.ts @@ -0,0 +1,40 @@ +import { AsyncIterator } from "asynciterator"; + +export default class Iterators { + + public static toArray(iterator: AsyncIterator): Promise { + + const array = []; + iterator.each((item: T) => array.push(item)); + + return new Promise((resolve) => { + iterator.on("end", () => resolve(array)); + }); + } + + public static getFirst(iterator: AsyncIterator): Promise { + return new Promise((resolve) => { + iterator.on("readable", () => { + resolve(iterator.read()); + }); + }); + } + + public static find(iterator: AsyncIterator, callback: (element: T) => boolean): Promise { + return new Promise((resolve, reject) => { + iterator.on("readable", () => { + let element = iterator.read(); + + while (element && !callback(element)) { + element = iterator.read(); + } + + if (element) { + resolve(element); + } + }); + + iterator.on("end", () => resolve(null)); + }); + } +} diff --git a/src/util/Rdf.ts b/src/util/Rdf.ts new file mode 100644 index 00000000..f776afc3 --- /dev/null +++ b/src/util/Rdf.ts @@ -0,0 +1,44 @@ +import { Triple } from "rdf-js"; + +export default class Rdf { + + public static matchesTriple(subject: string, predicate: string, object: string): (triple: Triple) => boolean { + return (triple: Triple) => { + if (subject && triple.subject.value !== subject) { + return false; + } + + if (predicate && triple.predicate.value !== predicate) { + return false; + } + + if (object && triple.object.value !== object) { + return false; + } + + return true; + }; + } + + public static transformPredicate(transformMap: { [oldPredicate: string]: string }, triple: Triple): Triple { + if (triple.predicate.value in transformMap) { + triple.predicate.value = transformMap[triple.predicate.value]; + } + return triple; + } + + public static transformObject(transformMap: { [oldObject: string]: string }, triple: Triple): Triple { + if (triple.object.value in transformMap) { + triple.object.value = transformMap[triple.object.value]; + } + return triple; + } + + public static logTripleTable(triples: Triple[]): void { + console.table(triples.map((triple: Triple) => ({ + subject: triple.subject.value, + predicate: triple.predicate.value, + object: triple.object.value, + }))); + } +} diff --git a/src/util/ReduceIterator.ts b/src/util/ReduceIterator.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/util/Units.test.ts b/src/util/Units.test.ts new file mode 100644 index 00000000..fc8ee6d1 --- /dev/null +++ b/src/util/Units.test.ts @@ -0,0 +1,49 @@ +import "jest"; +import { DistanceM, DurationMs, SpeedkmH } from "../interfaces/units"; +import Units from "./Units"; + +test("[Units] toSpeed", () => { + + const distance: DistanceM = 10000; + const duration: DurationMs = 3600000; + const speed: SpeedkmH = Units.toSpeed(distance, duration); + + expect(speed).toBeDefined(); + expect(speed).toEqual(10); +}); + +test("[Units] toDuration", () => { + + const distance: DistanceM = 10000; + const speed: SpeedkmH = 10; + const duration: DurationMs = Units.toDuration(distance, speed); + + expect(duration).toBeDefined(); + expect(duration).toEqual(3600000); +}); + +test("[Units] toDistance", () => { + + const duration: DurationMs = 3600000; + const speed: SpeedkmH = 10; + const distance: DistanceM = Units.toDistance(speed, duration); + + expect(distance).toBeDefined(); + expect(distance).toEqual(10000); +}); + +test("[Units] fromHour", () => { + + const duration: DurationMs = Units.fromHours(1); + + expect(duration).toBeDefined(); + expect(duration).toEqual(3600000); +}); + +test("[Units] fromSeconds", () => { + + const duration: DurationMs = Units.fromSeconds(2); + + expect(duration).toBeDefined(); + expect(duration).toEqual(2000); +}); diff --git a/src/util/Units.ts b/src/util/Units.ts new file mode 100644 index 00000000..4a4337fb --- /dev/null +++ b/src/util/Units.ts @@ -0,0 +1,25 @@ +import { DistanceM, DurationMs, SpeedkmH } from "../interfaces/units"; + +export default class Units { + public static toSpeed(distance: DistanceM, duration: DurationMs): SpeedkmH { + return (distance / duration) * 3600; + } + + public static toDistance(duration: DurationMs, speed: SpeedkmH): DistanceM { + return (speed * duration) / 3600; + } + + public static toDuration(distance: DistanceM, speed: SpeedkmH): DurationMs { + // tslint:disable-next-line:no-bitwise + return ((distance / speed) * 3600 | 0); + } + + public static fromHours(hours: number): DurationMs { + return hours * 3600000; + } + + public static fromSeconds(seconds: number): DurationMs { + return seconds * 1000; + } + +} diff --git a/src/util/Vectors.ts b/src/util/Vectors.ts new file mode 100644 index 00000000..427fcb7e --- /dev/null +++ b/src/util/Vectors.ts @@ -0,0 +1,36 @@ +/** + * Helper class for vectors. + */ +export default class Vectors { + + public static shiftVector(vector: T, item: any): T { + vector.unshift(item); + vector.pop(); + return vector; + } + + public static minVector(keyExtractor: (component: any) => number, ...vectors: T[]): T { + if (!vectors || !vectors[0]) { + return; + } + + const resultVector: T = vectors[0]; + + for (let index = 0 ; index < vectors[0].length && vectors.length > 1; index++) { + let currentMinimum = keyExtractor(resultVector[index]); + + for (let vectorIndex = 1 ; vectorIndex < vectors.length ; vectorIndex++) { + const vector = vectors[vectorIndex]; + const key = keyExtractor(vector[index]); + + if (key < currentMinimum) { + resultVector[index] = vector[index]; + currentMinimum = key; + } + } + + } + + return resultVector; + } +} diff --git a/tsconfig.json b/tsconfig.json index 3cc42952..b381d735 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "emitDecoratorMetadata": true, "sourceMap": true, "declaration": true, - "outDir": "dist", + "outDir": "lib", "esModuleInterop": true, "allowSyntheticDefaultImports": true }, diff --git a/tslint.json b/tslint.json index 293e7a18..8d17f7e4 100644 --- a/tslint.json +++ b/tslint.json @@ -6,7 +6,8 @@ "jsRules": {}, "rules": { "no-console": false, - "object-literal-sort-keys": false + "object-literal-sort-keys": false, + "no-empty-interface": false }, "rulesDirectory": [] } diff --git a/typedoc.js b/typedoc.js new file mode 100644 index 00000000..f888992e --- /dev/null +++ b/typedoc.js @@ -0,0 +1,12 @@ +module.exports = { + out: 'docs/code', + includes: 'src/', + exclude: [ + '**/*+(config|test).ts', + ], + mode: 'file', + excludePrivate: true, + excludeNotExported: true, + excludeExternals: true, + theme: 'minimal', +}; diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..cd163ddc --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,25 @@ +const path = require("path"); + +module.exports = { + entry: "./src/index.ts", + devtool: 'cheap-module-source-map', + module: { + rules: [ + { + test: /\.ts$/, + use: "ts-loader", + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: [".ts", ".js"] + }, + output: { + filename: "bundle.js", + path: path.resolve(__dirname, 'dist'), + library: 'Planner', + libraryTarget: 'umd', + libraryExport: 'default', + } +};