diff --git a/README.adoc b/README.adoc index 0f9297c18e..6239e19ff4 100644 --- a/README.adoc +++ b/README.adoc @@ -91,3 +91,4 @@ make sure the installer actually downloads and installs the new DFX release the job which will monitor the aforementioned `publish.install-sh.x86_64-linux` job for new builds, whenever there's a new build it will download the output (the CD script) and execute it. + diff --git a/assets.nix b/assets.nix index 6a419d45d3..13a1ccf914 100644 --- a/assets.nix +++ b/assets.nix @@ -1,5 +1,5 @@ { pkgs ? import ./nix {} -, bootstrap-js ? import ./src/bootstrap { inherit pkgs; } +, bootstrap-js ? import ./nix/agent-js/bootstrap-js.nix { inherit pkgs; } , distributed-canisters ? import ./distributed-canisters.nix { inherit pkgs; } }: pkgs.runCommandNoCCLocal "assets" {} '' @@ -14,7 +14,7 @@ pkgs.runCommandNoCCLocal "assets" {} '' # Install bootstrap mkdir $out/bootstrap - cp -R ${bootstrap-js.out}/* $out/bootstrap/ + cp -R ${bootstrap-js.dist}/* $out/bootstrap/ cp -R ${distributed-canisters} $out/canisters '' diff --git a/default.nix b/default.nix index 78c55573a3..685c866c30 100644 --- a/default.nix +++ b/default.nix @@ -7,17 +7,16 @@ , labels ? {} }: rec { - dfx = import ./dfx.nix { inherit pkgs agent-js assets; }; + dfx = import ./dfx.nix { inherit pkgs assets; }; e2e-tests = import ./e2e/bats { inherit pkgs dfx; }; e2e-tests-ic-ref = import ./e2e/bats { inherit pkgs dfx; use_ic_ref = true; }; - node-e2e-tests = import ./e2e/node { inherit pkgs dfx; }; # Agents in varous languages - agent-js = import ./src/agent/javascript { inherit pkgs; }; + agent-js-monorepo = pkgs.agent-js-monorepo; # Bootstrap frontend. - bootstrap-js = import ./src/bootstrap { inherit pkgs agent-js; }; + bootstrap-js = import ./nix/agent-js/bootstrap-js.nix { inherit system pkgs; }; cargo-audit = import ./cargo-audit.nix { inherit pkgs RustSec-advisory-db; }; @@ -34,7 +33,6 @@ rec { # `shell.nix` in the root to provide an environment which is the composition # of all the shells here. shells = { - js-user-library = import ./src/agent/javascript/shell.nix { inherit pkgs agent-js; }; rust-workspace = dfx.shell; }; diff --git a/dfx.nix b/dfx.nix index f76418ac54..2901302b4e 100644 --- a/dfx.nix +++ b/dfx.nix @@ -8,7 +8,6 @@ { pkgs ? import ./nix { inherit system; } , system ? builtins.currentSystem -, agent-js ? import ./src/agent/javascript { inherit pkgs; } , assets ? import ./assets.nix { inherit pkgs; } }: let diff --git a/e2e/node/.prettierrc b/e2e/node/.prettierrc deleted file mode 100644 index e3291ef711..0000000000 --- a/e2e/node/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "trailingComma": "all", - "tabWidth": 2, - "printWidth": 100, - "semi": true, - "bracketSpacing": true, - "useTabs": false, - "singleQuote": true, - "arrowParens": "avoid" -} diff --git a/e2e/node/README.adoc b/e2e/node/README.adoc deleted file mode 100644 index 8198416f91..0000000000 --- a/e2e/node/README.adoc +++ /dev/null @@ -1,54 +0,0 @@ -= Node End-to-End Tests - -== High level overview - -These tests are composed of two parts; - -1. a Nix script that installs the Agent in the execution location, as if it was an NPM - package. This is done by building the NPM Package, and the JS Agent derivation outputting - 2 outputs; the NPM package itself (in a packed format), and its node_modules which are - then copied in the execution folder for these tests. -2. a Jest framework in TypeScript that runs and validate the tests. - -The result is you build your tests as you would with Jest. You can import the JavaScript -agent by using `import * as agent from '@dfinity/agent'` which is as -close as it can be to the real world. - -== Starting / Stopping the Replica - -The `setup` Jest step starts the replica using `dfx replica`. The `teardown` step sends -a SIGTERM to the `dfx` process. Nix will wait for all children and descendants to be -stopped, so Nix will timeout and fail if the replica isn't properly killed. - -== Adding New Tests - -Adding a test is just a matter of having a file with a `.ts` extension anywhere outside -the root directory of tests and the `utils/` folder. This is driven by the -`jest.config.js` file which has a pattern matching all those files. - -We don't force users to have a `.test.ts` extension as this whole folder is meant to be -tests. It's just simpler that way. - -== Using HttpAgent - -The `utils/` folder contain an `agent.ts` file which exports an `HttpAgent` instance -which connects to the testing Replica. Unless required by your test to have a special -agent configuration, you should always reuse that one. - -== Creating and Using Canisters - -Right now, the way to add a canister is to manually build it and check in the canisters -WASM. This is a limitation of the current setup and will (hopefully) go away soon. - -Once the WASM is checked in, a canister `.ts` should be added which exports a factory. -That factory reads the WASM, creates an actor with a random canisterId, builds the IDL -manually (currently) and install the canister on the Replica. A good example of this -can be seen in `utils/canisters/counter.ts`. - -= TODOs - -- [ ] Add a dfx project derivation which generates the WASM and IDL through Nix - so it doesn't have to be checked in. -- [ ] Also, reuse canister IDs exposed by the dfx project derivation above instead - of generating a random one. This is important for testing canisters which - have inter-canister calls. diff --git a/e2e/node/basic/call.ts b/e2e/node/basic/call.ts deleted file mode 100644 index 6fedfde977..0000000000 --- a/e2e/node/basic/call.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { counterFactory } from '../utils/canisters'; - -test('can call a canister', async () => { - let counter = await counterFactory(); - - expect(+(await counter.read())).toEqual(0); - expect(+(await counter.inc_read())).toEqual(1); - await counter.write(10); - expect(+(await counter.read())).toEqual(10); - expect(+(await counter.inc_read())).toEqual(11); -}); diff --git a/e2e/node/default.nix b/e2e/node/default.nix deleted file mode 100644 index f9afac4bcf..0000000000 --- a/e2e/node/default.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ pkgs ? import ../../nix { inherit system; } -, system ? builtins.currentSystem -, dfx ? import ../../dfx.nix { inherit pkgs; } -, agent-js ? import ../../src/agent/javascript { inherit pkgs; } -}: -pkgs.napalm.buildPackage (pkgs.lib.noNixFiles (pkgs.lib.gitOnlySource ./.)) { - root = ./.; - name = "node-e2e-tests"; - buildInputs = [ dfx.standalone agent-js ]; - - npmCommands = [ - "npm install" - - # Monkey-patch the agent source into our install dir. napalm is unable - # to include dependencies from package-locks in places other than the - # build root. - ( - pkgs.writeScript "include-agent.sh" '' - #!${pkgs.stdenv.shell} - set -eo pipefail - - agent_node_modules="node_modules/@dfinity/agent" - mkdir -p $agent_node_modules - - tar xvzf ${agent-js.out}/dfinity-*.tgz --strip-component 1 --directory $agent_node_modules/ - cp -R ${agent-js.lib}/node_modules . - '' - ) - "npm run ci" - ]; - - installPhase = '' - echo Done. - touch $out - ''; -} diff --git a/e2e/node/identity/principal.ts b/e2e/node/identity/principal.ts deleted file mode 100644 index 1ab87b3078..0000000000 --- a/e2e/node/identity/principal.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { identityFactory } from '../utils/canisters'; - -test('has the same identity when calling a query or a call function', async () => { - const identity = await identityFactory(); - - const call = await identity.hashFromCall(); - const query = await identity.hashFromQuery(); - - expect(+call).toEqual(+query); -}); diff --git a/e2e/node/jest.config.js b/e2e/node/jest.config.js deleted file mode 100644 index 55ea4dec17..0000000000 --- a/e2e/node/jest.config.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - bail: false, - testTimeout: 60000, - globalSetup: './setup', - globalTeardown: './teardown', - setupFiles: [ - "./test-setup", - ], - setupFilesAfterEnv: [ - "jest-expect-message", - ], - // Since we're running e2e tests, ALL typescript files are up for grab. - testMatch: [ - "**/*.ts" - ], - testPathIgnorePatterns: [ - "/node_modules/", - "/utils/", - ], - transform: { - "^.+\\.ts$": "ts-jest" - } -}; diff --git a/e2e/node/package-lock.json b/e2e/node/package-lock.json deleted file mode 100644 index 57380582b6..0000000000 --- a/e2e/node/package-lock.json +++ /dev/null @@ -1,5174 +0,0 @@ -{ - "name": "@do-not-publish/ic-node-e2e-tests", - "version": "0.0.0-do-not-publish", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/core": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.6.tgz", - "integrity": "sha512-Sheg7yEJD51YHAvLEV/7Uvw95AeWqYPL3Vk3zGujJKIhJ+8oLw2ALaf3hbucILhKsgSoADOvtKRJuNVdcJkOrg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.6", - "@babel/helpers": "^7.8.4", - "@babel/parser": "^7.8.6", - "@babel/template": "^7.8.6", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.6", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "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": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.6.tgz", - "integrity": "sha512-4bpOR5ZBz+wWcMeVtcf7FbjcFzCp+817z2/gHNncIRcM9MmKzUhtWCYAq27RAfUrAFwb+OCG1s9WEaVxfi6cjg==", - "dev": true, - "requires": { - "@babel/types": "^7.8.6", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "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/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", - "dev": true - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helpers": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", - "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", - "dev": true, - "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.4", - "@babel/types": "^7.8.3" - } - }, - "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.6.tgz", - "integrity": "sha512-trGNYSfwq5s0SgM1BMEB8hX3NDmO7EP2wsDGDexiaKMB92BaRpS+qZfpkMqUBhcsOTBwNy9B/jieo4ad/t/z2g==", - "dev": true - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6" - } - }, - "@babel/traverse": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.6.tgz", - "integrity": "sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.6", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.6.tgz", - "integrity": "sha512-wqz7pgWMIrht3gquyEFPVXeXCti72Rm8ep9b5tQKz9Yg9LzJA3HxosF1SB3Kc81KD1A3XBkkVYtJvCKS2Z/QrA==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@cnakazawa/watch": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", - "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", - "dev": true, - "requires": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.0" - } - }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@trust/keyto": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@trust/keyto/-/keyto-0.3.7.tgz", - "integrity": "sha512-t5kWWCTkPgg24JWVuCTPMx7l13F7YHdxBeJkT1vmoHjROgiOIEAN8eeY+iRmP1Hwsx+S7U55HyuqSsECr08a8A==", - "dev": true, - "requires": { - "asn1.js": "^5.0.1", - "base64url": "^3.0.1", - "elliptic": "^6.4.1" - } - }, - "@trust/webcrypto": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@trust/webcrypto/-/webcrypto-0.9.2.tgz", - "integrity": "sha512-5iMAVcGYKhqLJGjefB1nzuQSqUJTru0nG4CytpBT/GGp1Piz/MVnj2jORdYf4JBYzggCIa8WZUr2rchP2Ngn/w==", - "dev": true, - "requires": { - "@trust/keyto": "^0.3.4", - "base64url": "^3.0.0", - "elliptic": "^6.4.0", - "node-rsa": "^0.4.0", - "text-encoding": "^0.6.1" - }, - "dependencies": { - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true - } - } - }, - "@types/babel__core": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.6.tgz", - "integrity": "sha512-tTnhWszAqvXnhW7m5jQU9PomXSiKXk2sFxpahXvI20SZKu9ylPi8WtIxueZ6ehDWikPT0jeFujMj3X4ZHuf3Tg==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", - "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", - "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.9.tgz", - "integrity": "sha512-jEFQ8L1tuvPjOI8lnpaf73oCJe+aoxL6ygqSy6c8LcW98zaC+4mzWuQIRCEvKeCOu+lbqdXcg4Uqmm1S8AP1tw==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/base64-js": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/base64-js/-/base64-js-1.2.5.tgz", - "integrity": "sha1-WCskdhaabLpGCiFNR2x0REHYc9U=", - "dev": true - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "24.9.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz", - "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==", - "dev": true, - "requires": { - "jest-diff": "^24.3.0" - } - }, - "@types/node": { - "version": "13.7.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.7.tgz", - "integrity": "sha512-Uo4chgKbnPNlxQwoFmYIwctkQVkMMmsAoGGU4JKwLuvBefF0pCq4FybNSnfkfRCpC7ZW7kttcC/TrRtAJsvGtg==", - "dev": true - }, - "@types/stack-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", - "dev": true - }, - "@types/yargs": { - "version": "13.0.8", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", - "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", - "dev": true - }, - "abab": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", - "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", - "dev": true - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-globals": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", - "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", - "dev": true, - "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true - } - } - }, - "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", - "dev": true - }, - "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "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" - } - }, - "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" - } - }, - "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": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "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=", - "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 - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "asn1.js": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.3.0.tgz", - "integrity": "sha512-WHnQJFcOrIWT1RLOkFFBQkFVvyt9BPOOrH+Dp152Zk4R993rSzXUGPmkybIcUFhHE2d/iHH+nCaOWVCDbO8fgA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "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-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "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=", - "dev": true - }, - "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", - "dev": true - }, - "babel-plugin-istanbul": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", - "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "find-up": "^3.0.0", - "istanbul-lib-instrument": "^3.3.0", - "test-exclude": "^5.2.3" - } - }, - "babel-preset-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", - "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", - "dev": true, - "requires": { - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "babel-plugin-jest-hoist": "^24.9.0" - }, - "dependencies": { - "babel-plugin-jest-hoist": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", - "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", - "dev": true, - "requires": { - "@types/babel__traverse": "^7.0.6" - } - } - } - }, - "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" - } - } - } - }, - "base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "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=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "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 - }, - "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": "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" - } - } - } - }, - "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==", - "dev": true - }, - "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 - } - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.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 - }, - "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 - }, - "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" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "capture-exit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", - "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", - "dev": true, - "requires": { - "rsvp": "^4.8.4" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "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" - } - } - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "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.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "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 - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "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-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "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" - } - }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "cssstyle": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", - "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, - "requires": { - "cssom": "0.3.x" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" - }, - "dependencies": { - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - } - } - }, - "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" - } - }, - "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=", - "dev": true - }, - "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" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "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": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true - }, - "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, - "requires": { - "webidl-conversions": "^4.0.2" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", - "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" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "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.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "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.14.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", - "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.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 - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "exec-sh": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", - "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", - "dev": true - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.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": "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" - } - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "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" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": 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" - } - } - } - }, - "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" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "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==", - "dev": true, - "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" - } - }, - "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.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "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, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "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.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "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.6", - "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.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "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.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": 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, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.7", - "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, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": 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.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "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.7.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": 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.7.1", - "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, - "optional": 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, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "optional": 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 - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "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=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "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" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "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 - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, - "requires": { - "ajv": "^6.5.5", - "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-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.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "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" - } - }, - "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": { - "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.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "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" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "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==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.1" - } - }, - "html-escaper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "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" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "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.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "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" - } - }, - "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-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "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-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.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" - }, - "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-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "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-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-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": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "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" - } - } - } - }, - "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" - } - }, - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "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 - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "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": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, - "requires": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", - "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0" - } - }, - "jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", - "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", - "dev": true, - "requires": { - "import-local": "^2.0.0", - "jest-cli": "^24.9.0" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/core": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", - "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/reporters": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-changed-files": "^24.9.0", - "jest-config": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-resolve-dependencies": "^24.9.0", - "jest-runner": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "jest-watcher": "^24.9.0", - "micromatch": "^3.1.10", - "p-each-series": "^1.0.0", - "realpath-native": "^1.1.0", - "rimraf": "^2.5.4", - "slash": "^2.0.0", - "strip-ansi": "^5.0.0" - } - }, - "@jest/environment": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", - "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", - "dev": true, - "requires": { - "@jest/fake-timers": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0" - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" - } - }, - "@jest/reporters": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", - "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", - "dev": true, - "requires": { - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.2", - "istanbul-lib-coverage": "^2.0.2", - "istanbul-lib-instrument": "^3.0.1", - "istanbul-lib-report": "^2.0.4", - "istanbul-lib-source-maps": "^3.0.1", - "istanbul-reports": "^2.2.6", - "jest-haste-map": "^24.9.0", - "jest-resolve": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.6.0", - "node-notifier": "^5.4.2", - "slash": "^2.0.0", - "source-map": "^0.6.0", - "string-length": "^2.0.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } - }, - "@jest/test-sequencer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", - "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", - "dev": true, - "requires": { - "@jest/test-result": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-runner": "^24.9.0", - "jest-runtime": "^24.9.0" - } - }, - "@jest/transform": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", - "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^24.9.0", - "babel-plugin-istanbul": "^5.1.0", - "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.1.15", - "jest-haste-map": "^24.9.0", - "jest-regex-util": "^24.9.0", - "jest-util": "^24.9.0", - "micromatch": "^3.1.10", - "pirates": "^4.0.1", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "2.4.1" - } - }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "babel-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", - "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", - "dev": true, - "requires": { - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/babel__core": "^7.1.0", - "babel-plugin-istanbul": "^5.1.0", - "babel-preset-jest": "^24.9.0", - "chalk": "^2.4.2", - "slash": "^2.0.0" - } - }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true - }, - "expect": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", - "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.9.0" - } - }, - "jest-changed-files": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", - "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "execa": "^1.0.0", - "throat": "^4.0.0" - } - }, - "jest-cli": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", - "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", - "dev": true, - "requires": { - "@jest/core": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "import-local": "^2.0.0", - "is-ci": "^2.0.0", - "jest-config": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "prompts": "^2.0.1", - "realpath-native": "^1.1.0", - "yargs": "^13.3.0" - } - }, - "jest-config": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", - "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^24.9.0", - "@jest/types": "^24.9.0", - "babel-jest": "^24.9.0", - "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^24.9.0", - "jest-environment-node": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "micromatch": "^3.1.10", - "pretty-format": "^24.9.0", - "realpath-native": "^1.1.0" - } - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-docblock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", - "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", - "dev": true, - "requires": { - "detect-newline": "^2.1.0" - } - }, - "jest-each": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", - "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "jest-util": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-environment-jsdom": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", - "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", - "dev": true, - "requires": { - "@jest/environment": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-util": "^24.9.0", - "jsdom": "^11.5.1" - } - }, - "jest-environment-node": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", - "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", - "dev": true, - "requires": { - "@jest/environment": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-util": "^24.9.0" - } - }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, - "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" - } - }, - "jest-jasmine2": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", - "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "co": "^4.6.0", - "expect": "^24.9.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "pretty-format": "^24.9.0", - "throat": "^4.0.0" - } - }, - "jest-leak-detector": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", - "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", - "dev": true, - "requires": { - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, - "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true - }, - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - }, - "jest-resolve-dependencies": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", - "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-snapshot": "^24.9.0" - } - }, - "jest-runner": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", - "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.4.2", - "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-config": "^24.9.0", - "jest-docblock": "^24.3.0", - "jest-haste-map": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-leak-detector": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.6.0", - "source-map-support": "^0.5.6", - "throat": "^4.0.0" - } - }, - "jest-runtime": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", - "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.9.0", - "@jest/source-map": "^24.3.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.1.15", - "jest-config": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "strip-bom": "^3.0.0", - "yargs": "^13.3.0" - } - }, - "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", - "dev": true - }, - "jest-snapshot": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", - "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "expect": "^24.9.0", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^24.9.0", - "semver": "^6.2.0" - } - }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - } - }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" - } - }, - "jest-watcher": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", - "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", - "dev": true, - "requires": { - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "jest-util": "^24.9.0", - "string-length": "^2.0.0" - } - }, - "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" - } - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - } - }, - "sane": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", - "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", - "dev": true, - "requires": { - "@cnakazawa/watch": "^1.0.3", - "anymatch": "^2.0.0", - "capture-exit": "^2.0.0", - "exec-sh": "^0.3.2", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-expect-message": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/jest-expect-message/-/jest-expect-message-1.0.2.tgz", - "integrity": "sha512-WFiXMgwS2lOqQZt1iJMI/hOXpUm32X+ApsuzYcQpW5m16Pv6/Gd9kgC+Q+Q1YVNU04kYcAOv9NXMnjg6kKUy6Q==", - "dev": true - }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, - "jest-pnp-resolver": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", - "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", - "dev": true - }, - "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 - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "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=", - "dev": true - }, - "jsdom": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", - "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", - "dev": true, - "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": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "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=", - "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 - }, - "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=", - "dev": true - }, - "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "left-pad": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.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" - } - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "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" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "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-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" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "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" - } - } - } - }, - "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", - "dev": true, - "requires": { - "mime-db": "1.43.0" - } - }, - "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": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "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.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "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" - } - }, - "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 - }, - "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-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "dev": true - }, - "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-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, - "node-notifier": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", - "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", - "dev": true, - "requires": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" - } - }, - "node-rsa": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-0.4.2.tgz", - "integrity": "sha1-1jkXKewWqDDtWjgEKzFX0tXXJTA=", - "dev": true, - "requires": { - "asn1": "0.2.3" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - } - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.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" - } - }, - "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "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" - } - }, - "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" - } - } - } - }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "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" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.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" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "p-each-series": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", - "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", - "dev": true, - "requires": { - "p-reduce": "^1.0.0" - } - }, - "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-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", - "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-reduce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "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": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } - }, - "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" - } - }, - "pn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true - }, - "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 - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", - "dev": true - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - } - }, - "prompts": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.1.tgz", - "integrity": "sha512-qIP2lQyCwYbdzcqHIUi2HAxiWixhoM9OdLCWf8txXsapC/X9YdsCoeyRIXE/GP+Q0J37Q7+XN/MFqbUa7IzXNA==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.4" - } - }, - "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "react-is": { - "version": "16.13.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz", - "integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==", - "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - } - }, - "realpath-native": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", - "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", - "dev": true, - "requires": { - "util.promisify": "^1.0.0" - } - }, - "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 - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "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.3", - "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.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", - "dev": true, - "requires": { - "request-promise-core": "1.1.3", - "stealthy-require": "^1.1.1", - "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": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "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.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rsvp": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", - "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", - "dev": true - }, - "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==", - "dev": true - }, - "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==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "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.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "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" - } - } - } - }, - "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 - }, - "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": "1.0.4", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.4.tgz", - "integrity": "sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "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": { - "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" - } - } - } - }, - "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" - }, - "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" - } - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "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.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "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 - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "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.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "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.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "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" - } - }, - "stack-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", - "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", - "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=", - "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": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "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": "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" - } - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", - "dev": true, - "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - } - }, - "text-encoding": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", - "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", - "dev": true - }, - "throat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", - "dev": true - }, - "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "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" - }, - "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" - } - } - } - }, - "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" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "ts-jest": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.3.0.tgz", - "integrity": "sha512-Hb94C/+QRIgjVZlJyiWwouYUF+siNJHJHknyspaOcZ+OQAIdFG/UrdQVXw/0B8Z3No34xkUXZJpOTy9alOWdVQ==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "buffer-from": "1.x", - "fast-json-stable-stringify": "2.x", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "mkdirp": "0.x", - "resolve": "1.x", - "semver": "^5.5", - "yargs-parser": "10.x" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "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" - } - } - } - }, - "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", - "dev": true - }, - "tslint": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", - "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - } - }, - "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" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "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=", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "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 - } - } - }, - "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" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "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.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "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=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "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=", - "dev": true, - "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" - } - }, - "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==", - "dev": true - }, - "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==", - "dev": true, - "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==", - "dev": true - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", - "dev": true, - "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 - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", - "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", - "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==", - "dev": true, - "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==", - "dev": true - }, - "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 - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } -} diff --git a/e2e/node/package.json b/e2e/node/package.json deleted file mode 100644 index 6629949a4d..0000000000 --- a/e2e/node/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "private": true, - "name": "@do-not-publish/ic-node-e2e-tests", - "version": "0.0.0-do-not-publish", - "scripts": { - "ci": "npm run test", - "test": "jest --verbose" - }, - "dependencies": {}, - "devDependencies": { - "@trust/webcrypto": "^0.9.2", - "@types/base64-js": "^1.2.5", - "@types/jest": "^24.0.18", - "@types/node": "^13.7.7", - "jest": "^24.9.0", - "jest-expect-message": "^1.0.2", - "node-fetch": "2.6.0", - "prettier": "^1.19.1", - "text-encoding": "^0.7.0", - "ts-jest": "^24.2.0", - "tslint": "^5.20.0", - "typescript": "^3.6.3", - "whatwg-fetch": "^3.0.0" - } -} diff --git a/e2e/node/setup.js b/e2e/node/setup.js deleted file mode 100644 index b5ba53d539..0000000000 --- a/e2e/node/setup.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = function() { - // Run the Replica by using `dfx start`. - const { spawn } = require('child_process'); - global.replicaProcess = spawn('dfx', ['replica', '--port=8080'], { stdio: 'inherit' }); - - return new Promise(resolve => setTimeout(resolve, 5000)); -}; diff --git a/e2e/node/teardown.js b/e2e/node/teardown.js deleted file mode 100644 index 472fde9baf..0000000000 --- a/e2e/node/teardown.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = function() { - // Sending SIGINT here since the Replica process isn't actually the replica - // but `dfx replica`, which should be interupted to clean up properly. - // (ie. if directly killed it will keep the replica process running in - // the background). - global.replicaProcess.kill('SIGTERM'); - - // Give the replica a second to gather its things and quit. - // We unfortunately cannot exit our own process here because we don't know - // the status of the tests (fail/success). - return new Promise(resolve => setTimeout(resolve, 1000)); -}; diff --git a/e2e/node/test-setup.js b/e2e/node/test-setup.js deleted file mode 100644 index 1e35618217..0000000000 --- a/e2e/node/test-setup.js +++ /dev/null @@ -1,12 +0,0 @@ -// This file may be used to polyfill features that aren't available in the test -// environment, i.e. JSDom. -// -// We sometimes need to do this because our target browsers are expected to have -// a feature that JSDom doesn't. -// -// Note that we can use webpack configuration to make some features available to -// Node.js in a similar way. - -window.crypto = require('@trust/webcrypto'); -window.TextEncoder = require('text-encoding').TextEncoder; -window.fetch = require('node-fetch'); diff --git a/e2e/node/tsconfig.json b/e2e/node/tsconfig.json deleted file mode 100644 index 555dcc808f..0000000000 --- a/e2e/node/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "incremental": true, - "target": "es2017", - "module": "commonjs", - "lib": [ - "dom", - "es2017" - ], - "declaration": true, - "sourceMap": true, - "tsBuildInfoFile": "./build_info.json", - "strict": true, - "baseUrl": "./", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true - } -} diff --git a/e2e/node/utils/agent.ts b/e2e/node/utils/agent.ts deleted file mode 100644 index 421849ec7a..0000000000 --- a/e2e/node/utils/agent.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { - HttpAgent, - Principal, - generateKeyPair, - makeAuthTransform, - makeNonceTransform, -} from '@dfinity/agent'; - -const keyPair = generateKeyPair(); -const principal = Principal.selfAuthenticating(keyPair.publicKey); - -export const httpAgent = new HttpAgent({ host: 'http://localhost:8080', principal }); -httpAgent.addTransform(makeNonceTransform()); -httpAgent.setAuthTransform(makeAuthTransform(keyPair)); \ No newline at end of file diff --git a/e2e/node/utils/canisters/counter.ts b/e2e/node/utils/canisters/counter.ts deleted file mode 100644 index b106a31170..0000000000 --- a/e2e/node/utils/canisters/counter.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Actor, IDL, blobFromUint8Array } from '@dfinity/agent'; -import * as path from 'path'; -import { readFileSync } from 'fs'; -import { httpAgent } from '../agent'; - -const wasm = readFileSync(path.join(__dirname, 'counter.wasm')); - -type CounterActor = Actor & { - read(): Promise; - inc_read(): Promise; - inc(): Promise; - write(n: number): Promise; -}; - -const factory: IDL.InterfaceFactory = ({ IDL }) => - IDL.Service({ - read: IDL.Func([], [IDL.Nat], ['query']), - inc_read: IDL.Func([], [IDL.Nat], []), - inc: IDL.Func([], [], []), - write: IDL.Func([IDL.Nat], [], []), - }); - -// TODO(hansl): Add a type to create an Actor interface from a IDL.Service definition. -export async function counterFactory(): Promise { - return ((await Actor.createAndInstallCanister( - factory, - { - module: blobFromUint8Array(wasm), - }, - { - agent: httpAgent, - }, - )) as unknown) as CounterActor; -} diff --git a/e2e/node/utils/canisters/counter.wasm b/e2e/node/utils/canisters/counter.wasm deleted file mode 100644 index 9653efbc6e..0000000000 Binary files a/e2e/node/utils/canisters/counter.wasm and /dev/null differ diff --git a/e2e/node/utils/canisters/identity.ts b/e2e/node/utils/canisters/identity.ts deleted file mode 100644 index d3b2200c05..0000000000 --- a/e2e/node/utils/canisters/identity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Actor, IDL, blobFromUint8Array } from '@dfinity/agent'; -import * as path from 'path'; -import { readFileSync } from 'fs'; -import { httpAgent } from '../agent'; -import { default as factory, Identity } from './identity/main.did'; - -const wasm = readFileSync(path.join(__dirname, 'identity/main.wasm')); - -// TODO(hansl): Add a type to create an Actor interface from a IDL.Service definition. -export async function identityFactory(): Promise { - return ((await Actor.createAndInstallCanister( - factory, - { - module: blobFromUint8Array(wasm), - }, - { - agent: httpAgent, - }, - )) as unknown) as Identity; -} diff --git a/e2e/node/utils/canisters/identity/main.did.ts b/e2e/node/utils/canisters/identity/main.did.ts deleted file mode 100644 index c55d43eb19..0000000000 --- a/e2e/node/utils/canisters/identity/main.did.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Actor, IDL } from '@dfinity/agent'; - -export type Identity = Actor & { - hashFromCall(): Promise; - hashFromQuery(): Promise; -}; - -const factory: IDL.InterfaceFactory = ({ IDL }: any) => { - return IDL.Service({ - hashFromCall: IDL.Func([], [IDL.Nat], []), - hashFromQuery: IDL.Func([], [IDL.Nat], ['query']), - }); -}; -export default factory; diff --git a/e2e/node/utils/canisters/identity/main.mo b/e2e/node/utils/canisters/identity/main.mo deleted file mode 100644 index 41c00475ab..0000000000 --- a/e2e/node/utils/canisters/identity/main.mo +++ /dev/null @@ -1,11 +0,0 @@ -import Prim "mo:prim"; -import P "mo:base/Principal"; - -actor { - public shared(msg) func hashFromCall(): async Nat { - Prim.word32ToNat(P.hash(msg.caller)) - }; - public shared query(msg) func hashFromQuery() : async Nat { - Prim.word32ToNat(P.hash(msg.caller)) - }; -}; diff --git a/e2e/node/utils/canisters/identity/main.wasm b/e2e/node/utils/canisters/identity/main.wasm deleted file mode 100644 index 37ac09bf93..0000000000 Binary files a/e2e/node/utils/canisters/identity/main.wasm and /dev/null differ diff --git a/e2e/node/utils/canisters/index.ts b/e2e/node/utils/canisters/index.ts deleted file mode 100644 index e789a2d1ee..0000000000 --- a/e2e/node/utils/canisters/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './counter'; -export * from './identity'; diff --git a/nix/agent-js/agent-js-monorepo.nix b/nix/agent-js/agent-js-monorepo.nix new file mode 100644 index 0000000000..4f7624deaa --- /dev/null +++ b/nix/agent-js/agent-js-monorepo.nix @@ -0,0 +1,45 @@ +{ pkgs ? import ../. { inherit system; } +, system ? builtins.currentSystem + # This should be a fs path to a checked-out agent-js git repo. + # e.g. via niv at `nix-instantiate nix -A sources.agent-js-monorepo --eval` +, agent-js-monorepo-src +, agentJsMonorepoTools ? import ./monorepo-tools.nix { inherit pkgs system; } +}: +let + monorepo = pkgs.napalm.buildPackage agent-js-monorepo-src { + name = "agent-js-monorepo"; + propagatedBuildInputs = [ (agentJsMonorepoTools agent-js-monorepo-src) ]; + outputs = [ "out" "lib" "agent" "bootstrap" ]; + configureScript = builtins.toFile "tmp-nix-configure.sh" '' + export HOME=$(mktemp -d) + ''; + npmCommands = [ + # Do this with --ignore-scripts to ensure we fetch deps, but don't trigger any npm scripts. + # This is to allow for npm scripts that depend on dep's npm bin scripts. + # Those scripts may have shebangs in them, and nix can only patchShebangs after each command. + # So we fetch deps, let it patchShebangs, and then npm install again w/ postinstall scripts + "npm install --ignore-scripts" + "npm install" + ]; + installPhase = '' + # $out: Everything! + mkdir -p $out + cp -R ./* $out/ + + # $lib/node_modules: fetched npm dependencies + mkdir -p $lib + test -d node_modules && cp -R node_modules $lib || true + + # $agent: npm subpackage @dfinity/agent + mkdir -p $agent + cp -R node_modules $agent/ + cp -R ./packages/agent/* $agent/ + + # $bootstrap: npm subpackage @dfinity/bootstrap + mkdir -p $bootstrap + cp -R $out/node_modules $bootstrap/ + cp -R ./packages/bootstrap/* $bootstrap/ + ''; + }; +in +monorepo diff --git a/nix/agent-js/bootstrap-js.nix b/nix/agent-js/bootstrap-js.nix new file mode 100644 index 0000000000..db647aac22 --- /dev/null +++ b/nix/agent-js/bootstrap-js.nix @@ -0,0 +1,40 @@ +{ pkgs ? import ../. { inherit system; }, system ? builtins.currentSystem }: +pkgs.stdenv.mkDerivation { + name = "agent-js-monorepo-package-bootstrap"; + src = "${pkgs.agent-js-monorepo}"; + buildInputs = [ + pkgs.agent-js-monorepo + pkgs.nodejs + ]; + outputs = [ + "out" + "lib" + "dist" + ]; + configurePhase = '' + export HOME=$(mktemp -d) + ''; + unpackPhase = '' + mkdir bootstrap-bundle + cp -R ${pkgs.agent-js-monorepo}/* bootstrap-bundle/ + ''; + installPhase = '' + # $out: everything + mkdir -p $out + cp -R ${pkgs.agent-js-monorepo.bootstrap}/* $out/ + + # $lib/node_modules: node_modules dir that must be resolvable by npm + # for future build steps to work (e.g. at ../../node_modules) + mkdir -p $lib + if test -d node_modules; then + cp -R node_modules $lib; + fi + + # $dist: Store src files as outputed from typescript compiler + mkdir -p $dist + dist_src="bootstrap-bundle/packages/bootstrap/dist" + if test -d "$dist_src"; then + cp -R $dist_src/* $dist/ + fi + ''; +} diff --git a/nix/agent-js/monorepo-tools.nix b/nix/agent-js/monorepo-tools.nix new file mode 100644 index 0000000000..53299eac60 --- /dev/null +++ b/nix/agent-js/monorepo-tools.nix @@ -0,0 +1,26 @@ +{ pkgs ? import ../. { inherit system; }, system ? builtins.currentSystem }: +let + # derivation that has all system dependencies required to build the npm monorepo: + # * npm requires python3 to build with gyp + # * on mac, npm may try to use fsevents + agentJsMonorepoTools = src: + pkgs.stdenv.mkDerivation { + inherit src; + name = "agent-js-monorepo-systemRequirements"; + propagatedNativeBuildInputs = [ + # Required by node-gyp + pkgs.python3 + ]; + propagatedBuildInputs = [ + ( + pkgs.lib.optional pkgs.stdenv.isDarwin + # Required by fsevents + pkgs.darwin.apple_sdk.frameworks.CoreServices + ) + ]; + installPhase = '' + mkdir -p $out + ''; + }; +in +agentJsMonorepoTools diff --git a/nix/default.nix b/nix/default.nix index b1ee8c3cd7..0b766936bf 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -43,6 +43,10 @@ let napalm = self.callPackage self.sources.napalm { pkgs = self // { nodejs = self.nodejs-12_x; }; }; + agent-js-monorepo = import ./agent-js/agent-js-monorepo.nix { + inherit system pkgs; + agent-js-monorepo-src = self.sources.agent-js-monorepo; + }; ic-ref = (import self.sources.ic-ref { inherit (self) system; }).ic-ref; nix-fmt = nixFmt.fmt; diff --git a/nix/sources.json b/nix/sources.json index eaccca3d1f..ecaec21d77 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -12,6 +12,12 @@ "url": "https://github.com/RustSec/advisory-db/archive/49dba073a8966457720ac568c68d332a53fd1717.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, + "agent-js-monorepo": { + "ref": "master", + "repo": "ssh://git@github.com/dfinity-lab/agent-js", + "rev": "5799552008dff90ee2fcc4de06206a0fa2ee77d1", + "type": "git" + }, "bats-support": { "branch": "v0.3.0", "builtin": false, diff --git a/src/agent/javascript/.gitignore b/src/agent/javascript/.gitignore deleted file mode 100644 index d0ead26ec0..0000000000 --- a/src/agent/javascript/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -build_info.json -node_modules/ -dist/ -**/*.js -**/*.js.map -**/*.d.ts - -# Cannot ignore .d.ts files in types/ -!types/**/*.d.ts - -# Cannot ignore setup files for webpack and jest, which are still JavaScript. -!webpack.config.js -!jest.config.js -!test-setup.js diff --git a/src/agent/javascript/.npmignore b/src/agent/javascript/.npmignore deleted file mode 100644 index 903cf392c9..0000000000 --- a/src/agent/javascript/.npmignore +++ /dev/null @@ -1,12 +0,0 @@ -# We work with a safelist here, so block everything that's not permitted, and add packages -# that are. -** - -!src/**/*.d.ts -!src/**/*.js -!types/**/*.d.ts -!package.json -!README.md - -# The following line further removes all test files (which matches .js and .d.ts). -src/**/*.test.* diff --git a/src/agent/javascript/.prettierrc b/src/agent/javascript/.prettierrc deleted file mode 100644 index 4592d0205d..0000000000 --- a/src/agent/javascript/.prettierrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "trailingComma": "all", - "tabWidth": 2, - "printWidth": 100, - "semi": true, - "bracketSpacing": true, - "useTabs": false, - "singleQuote": true, - "quoteProps": "consistent", - "arrowParens": "avoid" -} diff --git a/src/agent/javascript/INTERNAL.adoc b/src/agent/javascript/INTERNAL.adoc deleted file mode 100644 index ab0811a27a..0000000000 --- a/src/agent/javascript/INTERNAL.adoc +++ /dev/null @@ -1,20 +0,0 @@ -= JavaScript User Library - -This is an internal document and is not published to NPM. The public facing README is in -`./README.md`. This file can be safely removed once we are open sourced. - -Package: `@dfinity/agent` - -== Development - -=== How to build and use locally - -In this repo: - -[source,bash] -cd src/agent/javascript # You are here -npm install -npm run bundle -JS_AGENT_PATH=$(pwd) -cd MY_PROJECT_PATH ## <<<<< Put in the project you want to test. -npm install ${JS_AGENT_PATH} ## This will likely create a symlink. diff --git a/src/agent/javascript/README.md b/src/agent/javascript/README.md deleted file mode 100644 index fdba619a8f..0000000000 --- a/src/agent/javascript/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# JavaScript User Library - -Package: `@dfinity/agent` - -## API - -TBD. diff --git a/src/agent/javascript/default.nix b/src/agent/javascript/default.nix deleted file mode 100644 index aabcb44b7e..0000000000 --- a/src/agent/javascript/default.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ pkgs ? import ../../../nix { inherit system; } -, system ? builtins.currentSystem -}: -let - src = pkgs.lib.noNixFiles (pkgs.lib.gitOnlySource ./.); -in -pkgs.napalm.buildPackage src { - root = ./.; - name = "dfinity-sdk-agent-js"; - - outputs = [ "out" "lib" ]; - - propagatedNativeBuildInputs = [ - # Required by node-gyp - pkgs.python3 - ]; - propagatedBuildInputs = pkgs.lib.optional pkgs.stdenv.isDarwin - # Required by fsevents - pkgs.darwin.apple_sdk.frameworks.CoreServices; - - # ci script now does everything CI should do. Bundle is needed because it's the output - # of the nix derivation. - npmCommands = [ - "npm install" - "npm run ci" - "npm run bundle" - ]; - - installPhase = '' - npm pack - mkdir -p $out - - cp dfinity-*.tgz $out - - # Copy node_modules to be reused elsewhere. - mkdir -p $lib - cp -R node_modules $lib - ''; -} diff --git a/src/agent/javascript/jest.config.js b/src/agent/javascript/jest.config.js deleted file mode 100644 index f3d719b728..0000000000 --- a/src/agent/javascript/jest.config.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - bail: false, - setupFiles: [ - "./test-setup", - ], - setupFilesAfterEnv: [ - "jest-expect-message", - ], - testPathIgnorePatterns: [ - "/node_modules/", - "/out/", - ], - transform: { - "^.+\\.ts$": "ts-jest" - } -}; diff --git a/src/agent/javascript/shell.nix b/src/agent/javascript/shell.nix deleted file mode 100644 index bf74735a7f..0000000000 --- a/src/agent/javascript/shell.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ pkgs ? import ../../../nix { inherit system; } -, system ? builtins.currentSystem -, agent-js ? import ./. { inherit pkgs; } -}: -pkgs.mkCiShell { - name = "dfinity-js-user-library-env"; - inputsFrom = [ - agent-js - ]; -} diff --git a/src/agent/javascript/src/actor.test.ts b/src/agent/javascript/src/actor.test.ts deleted file mode 100644 index 44af029c0d..0000000000 --- a/src/agent/javascript/src/actor.test.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { Buffer } from 'buffer/'; -import { makeActorFactory } from './actor'; -import { HttpAgent } from './agent'; -import { makeAuthTransform, SenderPubKey, SenderSecretKey, SenderSig } from './auth'; -import * as cbor from './cbor'; -import { makeNonceTransform } from './http_agent_transforms'; -import { CallRequest, Signed, SubmitRequestType } from './http_agent_types'; -import * as IDL from './idl'; -import { Principal } from './principal'; -import { requestIdOf } from './request_id'; -import { blobFromHex, Nonce } from './types'; - -test('makeActor', async () => { - const actorInterface = () => { - return IDL.Service({ - greet: IDL.Func([IDL.Text], [IDL.Text]), - }); - }; - - const expectedReplyArg = blobFromHex(IDL.encode([IDL.Text], ['Hello, World!']).toString('hex')); - - const mockFetch: jest.Mock = jest - .fn() - .mockImplementationOnce((/*resource, init*/) => { - return Promise.resolve( - new Response(null, { - status: 202, - }), - ); - }) - .mockImplementationOnce((resource, init) => { - const body = cbor.encode({ status: 'unknown' }); - return Promise.resolve( - new Response(body, { - status: 200, - }), - ); - }) - .mockImplementationOnce((resource, init) => { - const body = cbor.encode({ status: 'received' }); - return Promise.resolve( - new Response(body, { - status: 200, - }), - ); - }) - .mockImplementationOnce((resource, init) => { - const body = cbor.encode({ status: 'processing' }); - return Promise.resolve( - new Response(body, { - status: 200, - }), - ); - }) - .mockImplementationOnce((resource, init) => { - const body = cbor.encode({ - status: 'replied', - reply: { - arg: expectedReplyArg, - }, - }); - return Promise.resolve( - new Response(body, { - status: 200, - }), - ); - }); - - const methodName = 'greet'; - const argValue = 'Name'; - - const arg = blobFromHex(IDL.encode([IDL.Text], [argValue]).toString('hex')); - - const canisterId = Principal.fromText('2chl6-4hpzw-vqaaa-aaaaa-c'); - const senderPubKey = Buffer.alloc(32, 0) as SenderPubKey; - const senderSecretKey = Buffer.alloc(32, 0) as SenderSecretKey; - const senderSig = Buffer.from([0]) as SenderSig; - const principal = await Principal.selfAuthenticating(senderPubKey); - const sender = principal.toBlob(); - - const nonces = [ - Buffer.from([0, 1, 2, 3, 4, 5, 6, 7]) as Nonce, - Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]) as Nonce, - Buffer.from([2, 3, 4, 5, 6, 7, 8, 9]) as Nonce, - Buffer.from([3, 4, 5, 6, 7, 8, 9, 0]) as Nonce, - Buffer.from([4, 5, 6, 7, 8, 9, 0, 1]) as Nonce, - ]; - - const expectedCallRequest = { - content: { - request_type: SubmitRequestType.Call, - canister_id: canisterId, - method_name: methodName, - arg, - nonce: nonces[0], - sender, - }, - sender_pubkey: senderPubKey, - sender_sig: senderSig, - } as Signed; - - const expectedCallRequestId = await requestIdOf(expectedCallRequest.content); - - let nonceCount = 0; - - const httpAgent = new HttpAgent({ - fetch: mockFetch, - principal, - }); - httpAgent.addTransform(makeNonceTransform(() => nonces[nonceCount++])); - httpAgent.setAuthTransform( - makeAuthTransform( - { - publicKey: senderPubKey, - secretKey: senderSecretKey, - }, - - () => Buffer.from([0]) as SenderSig, - ), - ); - - const actor = makeActorFactory(actorInterface)({ canisterId, agent: httpAgent }); - const reply = await actor.greet(argValue); - - expect(reply).toEqual(IDL.decode([IDL.Text], expectedReplyArg)[0]); - - const { calls, results } = mockFetch.mock; - - expect(calls.length).toBe(5); - expect(calls[0]).toEqual([ - 'http://localhost/api/v1/submit', - { - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - }, - body: cbor.encode(expectedCallRequest), - }, - ]); - - expect(calls[1]).toEqual([ - 'http://localhost/api/v1/read', - { - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - }, - body: cbor.encode({ - content: { - request_type: 'request_status', - request_id: expectedCallRequestId, - }, - sender_pubkey: senderPubKey, - sender_sig: senderSig, - }), - }, - ]); - - expect(calls[2][0]).toBe('http://localhost/api/v1/read'); - expect(calls[2][1]).toEqual({ - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - }, - body: cbor.encode({ - content: { - request_type: 'request_status', - request_id: expectedCallRequestId, - }, - sender_pubkey: senderPubKey, - sender_sig: senderSig, - }), - }); - - expect(calls[3][0]).toBe('http://localhost/api/v1/read'); - expect(calls[3][1]).toEqual({ - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - }, - body: cbor.encode({ - content: { - request_type: 'request_status', - request_id: expectedCallRequestId, - }, - sender_pubkey: senderPubKey, - sender_sig: senderSig, - }), - }); - - expect(calls[4][0]).toBe('http://localhost/api/v1/read'); - expect(calls[4][1]).toEqual({ - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - }, - body: cbor.encode({ - content: { - request_type: 'request_status', - request_id: expectedCallRequestId, - }, - sender_pubkey: senderPubKey, - sender_sig: senderSig, - }), - }); -}); - -// TODO: tests for rejected, unknown time out diff --git a/src/agent/javascript/src/actor.ts b/src/agent/javascript/src/actor.ts deleted file mode 100644 index fac3cb22ac..0000000000 --- a/src/agent/javascript/src/actor.ts +++ /dev/null @@ -1,352 +0,0 @@ -import { Buffer } from 'buffer/'; -import { Agent } from './agent'; -import { getManagementCanister } from './canisters/management'; -import { - QueryResponseStatus, - RequestStatusResponseReplied, - RequestStatusResponseStatus, -} from './http_agent_types'; -import * as IDL from './idl'; -import { GlobalInternetComputer } from './index'; -import { Principal } from './principal'; -import { RequestId, toHex as requestIdToHex } from './request_id'; -import { BinaryBlob } from './types'; - -declare const window: GlobalInternetComputer; -declare const global: GlobalInternetComputer; -declare const self: GlobalInternetComputer; - -function getDefaultAgent(): Agent { - const agent = - typeof window === 'undefined' - ? typeof global === 'undefined' - ? typeof self === 'undefined' - ? undefined - : self.ic.agent - : global.ic.agent - : window.ic.agent; - - if (!agent) { - throw new Error('No Agent could be found.'); - } - - return agent; -} - -/** - * Configuration to make calls to the Replica. - */ -export interface CallConfig { - agent?: Agent; - maxAttempts?: number; - throttleDurationInMSecs?: number; -} - -/** - * Configuration that can be passed to customize the Actor behaviour. - */ -export interface ActorConfig extends CallConfig { - canisterId: string | Principal; -} - -// TODO: move this to proper typing when Candid support TypeScript. -/** - * A subclass of an actor. Actor class itself is meant to be a based class. - */ -export type ActorSubclass Promise>> = Actor & T; - -/** - * The mode used when installing a canister. - */ -export enum CanisterInstallMode { - Install = 'install', - Reinstall = 'reinstall', - Upgrade = 'upgrade', -} - -/** - * Internal metadata for actors. It's an enhanced version of ActorConfig with - * some fields marked as required (as they are defaulted) and canisterId as - * a Principal type. - */ -interface ActorMetadata { - canisterId: Principal; - service: IDL.ServiceClass; - agent?: Agent; - maxAttempts: number; - throttleDurationInMSecs: number; -} - -const metadataSymbol = Symbol.for('ic-agent-metadata'); - -/** - * An actor base class. An actor is an object containing only functions that will - * return a promise. These functions are derived from the IDL definition. - */ -export class Actor { - /** - * Get the interface of an actor, in the form of an instance of a Service. - * @param actor The actor to get the interface of. - */ - public static interfaceOf(actor: Actor): IDL.ServiceClass { - return actor[metadataSymbol].service; - } - - public static canisterIdOf(actor: Actor): Principal { - return actor[metadataSymbol].canisterId; - } - - public static async install( - fields: { - module: BinaryBlob; - mode?: CanisterInstallMode; - arg?: BinaryBlob; - computerAllocation?: number; - memoryAllocation?: number; - }, - config: ActorConfig, - ): Promise { - const mode = fields.mode === undefined ? CanisterInstallMode.Install : fields.mode; - // Need to transform the arg into a number array. - const arg = fields.arg ? [...fields.arg] : []; - // Same for module. - const wasmModule = [...fields.module]; - const canisterId = - typeof config.canisterId === 'string' - ? Principal.fromText(config.canisterId) - : config.canisterId; - const computerAllocation: [number] | [] = - fields.computerAllocation !== undefined ? [fields.computerAllocation] : []; - const memoryAllocation: [number] | [] = - fields.memoryAllocation !== undefined ? [fields.memoryAllocation] : []; - - await getManagementCanister(config).install_code({ - mode: { [mode]: null } as any, - arg, - wasm_module: wasmModule, - canister_id: canisterId, - compute_allocation: computerAllocation, - memory_allocation: memoryAllocation, - }); - } - - public static async createCanister(config?: CallConfig): Promise { - const { canister_id: canisterId } = await getManagementCanister(config || {}).create_canister(); - - return canisterId; - } - - public static async createAndInstallCanister( - interfaceFactory: IDL.InterfaceFactory, - fields: { - module: BinaryBlob; - arg?: BinaryBlob; - }, - config?: CallConfig, - ): Promise { - const canisterId = await this.createCanister(config); - await this.install( - { - ...fields, - }, - { ...config, canisterId }, - ); - - return this.createActor(interfaceFactory, { ...config, canisterId }); - } - - public static createActorClass(interfaceFactory: IDL.InterfaceFactory): ActorConstructor { - const service = interfaceFactory({ IDL }); - - class CanisterActor extends Actor { - [x: string]: (...args: unknown[]) => Promise; - - constructor(config: ActorConfig) { - const canisterId = - typeof config.canisterId === 'string' - ? Principal.fromText(config.canisterId) - : config.canisterId; - - super({ - ...DEFAULT_ACTOR_CONFIG, - ...config, - canisterId, - service, - }); - } - } - - for (const [methodName, func] of service._fields) { - CanisterActor.prototype[methodName] = _createActorMethod(methodName, func); - } - - return CanisterActor; - } - - public static createActor< - T = Record Promise>> - >(interfaceFactory: IDL.InterfaceFactory, configuration: ActorConfig): ActorSubclass { - return (new (this.createActorClass(interfaceFactory))( - configuration, - ) as unknown) as ActorSubclass; - } - - private [metadataSymbol]: ActorMetadata; - - protected constructor(metadata: ActorMetadata) { - this[metadataSymbol] = metadata; - } -} - -// IDL functions can have multiple return values, so decoding always -// produces an array. Ensure that functions with single or zero return -// values behave as expected. -function decodeReturnValue(types: IDL.Type[], msg: BinaryBlob) { - const returnValues = IDL.decode(types, Buffer.from(msg)); - switch (returnValues.length) { - case 0: - return undefined; - case 1: - return returnValues[0]; - default: - return returnValues; - } -} - -const REQUEST_STATUS_RETRY_WAIT_DURATION_IN_MSECS = 500; -const DEFAULT_ACTOR_CONFIG = { - maxAttempts: 30, - throttleDurationInMSecs: REQUEST_STATUS_RETRY_WAIT_DURATION_IN_MSECS, -}; - -export type ActorConstructor = new (config: ActorConfig) => ActorSubclass; -export type ActorFactory = (config: ActorConfig) => ActorSubclass; - -function _createActorMethod( - methodName: string, - func: IDL.FuncClass, -): (...args: unknown[]) => Promise { - if (func.annotations.includes('query')) { - return async function (this: Actor, ...args: unknown[]) { - const agent = this[metadataSymbol].agent || getDefaultAgent(); - const cid = this[metadataSymbol].canisterId; - const arg = IDL.encode(func.argTypes, args) as BinaryBlob; - - const result = await agent.query(cid, { methodName, arg }); - - switch (result.status) { - case QueryResponseStatus.Rejected: - throw new Error( - `Query failed:\n` + - ` Status: ${result.status}\n` + - ` Message: ${result.reject_message}\n`, - ); - - case QueryResponseStatus.Replied: - return decodeReturnValue(func.retTypes, result.reply.arg); - } - }; - } else { - return async function (this: Actor, ...args: unknown[]) { - const agent = this[metadataSymbol].agent || getDefaultAgent(); - const cid = this[metadataSymbol].canisterId; - - const { maxAttempts, throttleDurationInMSecs } = this[metadataSymbol]; - const arg = IDL.encode(func.argTypes, args) as BinaryBlob; - const { requestId, response } = await agent.call(cid, { methodName, arg }); - - if (!response.ok) { - throw new Error( - [ - 'Call failed:', - ` Method: ${methodName}(${args})`, - ` Canister ID: ${cid.toHex()}`, - ` Request ID: ${requestIdToHex(requestId)}`, - ` HTTP status code: ${response.status}`, - ` HTTP status text: ${response.statusText}`, - ].join('\n'), - ); - } - - return _requestStatusAndLoop( - agent, - requestId, - status => { - if (status.reply.arg !== undefined) { - return decodeReturnValue(func.retTypes, status.reply.arg); - } else if (func.retTypes.length === 0) { - return undefined; - } else { - throw new Error(`Call was returned undefined, but type [${func.retTypes.join(',')}].`); - } - }, - maxAttempts, - maxAttempts, - throttleDurationInMSecs, - ); - }; - } -} - -async function _requestStatusAndLoop( - agent: Agent, - requestId: RequestId, - decoder: (response: RequestStatusResponseReplied) => T, - attempts: number, - maxAttempts: number, - throttle: number, -): Promise { - const status = await agent.requestStatus({ requestId }); - - switch (status.status) { - case RequestStatusResponseStatus.Replied: { - return decoder(status); - } - - case RequestStatusResponseStatus.Unknown: - case RequestStatusResponseStatus.Received: - case RequestStatusResponseStatus.Processing: - if (--attempts === 0) { - throw new Error( - `Failed to retrieve a reply for request after ${maxAttempts} attempts:\n` + - ` Request ID: ${requestIdToHex(requestId)}\n` + - ` Request status: ${status.status}\n`, - ); - } - - // Wait a little, then retry. - return new Promise(resolve => setTimeout(resolve, throttle)).then(() => - _requestStatusAndLoop(agent, requestId, decoder, attempts, maxAttempts, throttle), - ); - - case RequestStatusResponseStatus.Rejected: - throw new Error( - `Call was rejected:\n` + - ` Request ID: ${requestIdToHex(requestId)}\n` + - ` Reject code: ${status.reject_code}\n` + - ` Reject text: ${status.reject_message}\n`, - ); - } -} - -// Make an actor from an actor interface. -// -// Allows for one HTTP agent for the lifetime of the actor: -// -// ``` -// const actor = makeActor(actorInterface)({ agent }); -// const reply = await actor.greet(); -// ``` -// -// or using a different HTTP agent for the same actor if necessary: -// -// ``` -// const actor = makeActor(actorInterface); -// const reply1 = await actor(agent1).greet(); -// const reply2 = await actor(agent2).greet(); -// ``` -export function makeActorFactory(actorInterfaceFactory: IDL.InterfaceFactory): ActorFactory { - return (config: ActorConfig) => { - return Actor.createActor(actorInterfaceFactory, config); - }; -} diff --git a/src/agent/javascript/src/agent/api.ts b/src/agent/javascript/src/agent/api.ts deleted file mode 100644 index 9ec5803266..0000000000 --- a/src/agent/javascript/src/agent/api.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { ActorFactory } from '../actor'; -import { - QueryFields, - QueryResponse, - RequestStatusFields, - RequestStatusResponse, - SubmitResponse, -} from '../http_agent_types'; -import * as IDL from '../idl'; -import { Principal } from '../principal'; -import { BinaryBlob, JsonObject } from '../types'; - -// An Agent able to make calls and queries to a Replica. -export interface Agent { - requestStatus(fields: RequestStatusFields, principal?: Principal): Promise; - - call( - canisterId: Principal | string, - fields: { - methodName: string; - arg: BinaryBlob; - }, - principal?: Principal | Promise, - ): Promise; - - createCanister(principal?: Principal): Promise; - - status(): Promise; - - install( - canisterId: Principal | string, - fields: { - module: BinaryBlob; - arg?: BinaryBlob; - }, - principal?: Principal, - ): Promise; - - query( - canisterId: Principal | string, - fields: QueryFields, - principal?: Principal, - ): Promise; - - makeActorFactory(actorInterfaceFactory: IDL.InterfaceFactory): ActorFactory; -} diff --git a/src/agent/javascript/src/agent/http.ts b/src/agent/javascript/src/agent/http.ts deleted file mode 100644 index c793c411ca..0000000000 --- a/src/agent/javascript/src/agent/http.ts +++ /dev/null @@ -1,348 +0,0 @@ -import { Buffer } from 'buffer/'; -import { ActorFactory } from '../actor'; -import * as actor from '../actor'; -import { Agent } from '../agent'; -import * as cbor from '../cbor'; -import { - AuthHttpAgentRequestTransformFn, - Endpoint, - HttpAgentReadRequest, - HttpAgentRequest, - HttpAgentRequestTransformFn, - HttpAgentSubmitRequest, - QueryFields, - QueryResponse, - ReadRequest, - ReadRequestType, - ReadResponse, - RequestStatusFields, - RequestStatusResponse, - SignedHttpAgentRequest, - SubmitRequest, - SubmitRequestType, - SubmitResponse, -} from '../http_agent_types'; -import * as IDL from '../idl'; -import { Principal } from '../principal'; -import { requestIdOf } from '../request_id'; -import { BinaryBlob, blobFromHex, JsonObject } from '../types'; - -const API_VERSION = 'v1'; - -// HttpAgent options that can be used at construction. -export interface HttpAgentOptions { - // Another HttpAgent to inherit configuration (pipeline and fetch) of. This - // is only used at construction. - source?: HttpAgent; - - // A surrogate to the global fetch function. Useful for testing. - fetch?: typeof fetch; - - // The host to use for the client. By default, uses the same host as - // the current page. - host?: string; - - // The principal used to send messages. This cannot be empty at the request - // time (will throw). - principal?: Principal | Promise; - - credentials?: { - name: string; - password?: string; - }; -} - -declare const window: Window & { fetch: typeof fetch }; -declare const global: { fetch: typeof fetch }; -declare const self: { fetch: typeof fetch }; - -function getDefaultFetch(): typeof fetch { - const result = - typeof window === 'undefined' - ? typeof global === 'undefined' - ? typeof self === 'undefined' - ? undefined - : self.fetch.bind(self) - : global.fetch.bind(global) - : window.fetch.bind(window); - - if (!result) { - throw new Error('Could not find default `fetch` implementation.'); - } - - return result; -} - -// A HTTP agent allows users to interact with a client of the internet computer -// using the available methods. It exposes an API that closely follows the -// public view of the internet computer, and is not intended to be exposed -// directly to the majority of users due to its low-level interface. -// -// There is a pipeline to apply transformations to the request before sending -// it to the client. This is to decouple signature, nonce generation and -// other computations so that this class can stay as simple as possible while -// allowing extensions. -export class HttpAgent implements Agent { - private readonly _pipeline: HttpAgentRequestTransformFn[] = []; - private _authTransform: AuthHttpAgentRequestTransformFn | null = null; - private readonly _fetch: typeof fetch; - private readonly _host: URL; - private readonly _principal: Promise | null = null; - private readonly _credentials: string | undefined; - - constructor(options: HttpAgentOptions = {}) { - if (options.source) { - this._pipeline = [...options.source._pipeline]; - this._authTransform = options.source._authTransform; - this._principal = options.source._principal; - } - this._fetch = options.fetch || getDefaultFetch() || fetch.bind(global); - if (options.host) { - if (!options.host.match(/^[a-z]+:/) && typeof window !== 'undefined') { - this._host = new URL(window.location.protocol + '//' + options.host); - } else { - this._host = new URL(options.host); - } - } else { - const location = window?.location; - if (!location) { - throw new Error('Must specify a host to connect to.'); - } - this._host = new URL(location + ''); - } - if (options.principal) { - this._principal = Promise.resolve(options.principal); - } - if (options.credentials) { - const { name, password } = options.credentials; - this._credentials = `${name}${password ? ':' + password : ''}`; - } - } - - public addTransform(fn: HttpAgentRequestTransformFn, priority = fn.priority || 0) { - // Keep the pipeline sorted at all time, by priority. - const i = this._pipeline.findIndex(x => (x.priority || 0) < priority); - this._pipeline.splice(i >= 0 ? i : this._pipeline.length, 0, Object.assign(fn, { priority })); - } - - public setAuthTransform(fn: AuthHttpAgentRequestTransformFn) { - this._authTransform = fn; - } - - public async call( - canisterId: Principal | string, - fields: { - methodName: string; - arg: BinaryBlob; - }, - principal?: Principal | Promise, - ): Promise { - let p = this._principal || principal; - if (!p) { - throw new Error('No principal specified.'); - } - p = await Promise.resolve(p); - - return this.submit({ - request_type: SubmitRequestType.Call, - canister_id: typeof canisterId === 'string' ? Principal.fromText(canisterId) : canisterId, - method_name: fields.methodName, - arg: fields.arg, - sender: p.toBlob(), - }); - } - - public async install( - canisterId: Principal | string, - fields: { - module: BinaryBlob; - arg?: BinaryBlob; - }, - principal?: Principal, - ): Promise { - let p = this._principal || principal; - if (!p) { - throw new Error('No principal specified.'); - } - p = await Promise.resolve(p); - - return this.submit({ - request_type: SubmitRequestType.InstallCode, - canister_id: typeof canisterId === 'string' ? Principal.fromText(canisterId) : canisterId, - module: fields.module, - arg: fields.arg || blobFromHex(''), - sender: p.toBlob(), - }); - } - - public async createCanister(principal?: Principal): Promise { - let p = this._principal || principal; - if (!p) { - throw new Error('No principal specified.'); - } - p = await Promise.resolve(p); - - return this.submit({ - request_type: SubmitRequestType.CreateCanister, - sender: p.toBlob(), - }); - } - - public async query( - canisterId: Principal | string, - fields: QueryFields, - principal?: Principal, - ): Promise { - let p = this._principal || principal; - if (!p) { - throw new Error('No principal specified.'); - } - p = await Promise.resolve(p); - - return this.read({ - request_type: ReadRequestType.Query, - canister_id: typeof canisterId === 'string' ? Principal.fromText(canisterId) : canisterId, - method_name: fields.methodName, - arg: fields.arg, - sender: p.toBlob(), - }) as Promise; - } - - public async requestStatus( - fields: RequestStatusFields, - principal?: Principal, - ): Promise { - let p = this._principal || principal; - if (!p) { - throw new Error('No principal specified.'); - } - p = await Promise.resolve(p); - - return this.read({ - request_type: ReadRequestType.RequestStatus, - request_id: fields.requestId, - }) as Promise; - } - - public async status(): Promise { - const headers: Record = this._credentials - ? { - Authorization: 'Basic ' + btoa(this._credentials), - } - : {}; - - const response = await this._fetch( - '' + new URL(`/api/${API_VERSION}/${Endpoint.Status}`, this._host), - { headers }, - ); - - if (!response.ok) { - throw new Error( - `Server returned an error:\n` + - ` Code: ${response.status} (${response.statusText}\n)` + - ` Body: ${await response.text()}\n`, - ); - } - - const buffer = await response.arrayBuffer(); - return cbor.decode(new Uint8Array(buffer)); - } - - public makeActorFactory(actorInterfaceFactory: IDL.InterfaceFactory): ActorFactory { - return actor.makeActorFactory(actorInterfaceFactory); - } - - protected _transform( - request: HttpAgentRequest, - ): Promise { - let p = Promise.resolve(request); - - for (const fn of this._pipeline) { - p = p.then(r => fn(r).then(r2 => r2 || r)); - } - - if (this._authTransform != null) { - return p.then(this._authTransform); - } else { - return p; - } - } - - protected async submit(submit: SubmitRequest): Promise { - const transformedRequest = (await this._transform({ - request: { - body: null, - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - ...(this._credentials ? { Authorization: 'Basic ' + btoa(this._credentials) } : {}), - }, - }, - endpoint: Endpoint.Submit, - body: submit, - })) as HttpAgentSubmitRequest; - - const body = cbor.encode(transformedRequest.body); - - // Run both in parallel. The fetch is quite expensive, so we have plenty of time to - // calculate the requestId locally. - const [response, requestId] = await Promise.all([ - this._fetch('' + new URL(`/api/${API_VERSION}/${Endpoint.Submit}`, this._host), { - ...transformedRequest.request, - body, - }), - requestIdOf(submit), - ]); - - if (!response.ok) { - throw new Error( - `Server returned an error:\n` + - ` Code: ${response.status} (${response.statusText}\n)` + - ` Body: ${await response.text()}\n`, - ); - } - - return { - requestId, - response: { - ok: response.ok, - status: response.status, - statusText: response.statusText, - }, - }; - } - - protected async read(request: ReadRequest): Promise { - const transformedRequest = (await this._transform({ - request: { - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - ...(this._credentials ? { Authorization: 'Basic ' + btoa(this._credentials) } : {}), - }, - }, - endpoint: Endpoint.Read, - body: request, - })) as HttpAgentReadRequest; - - const body = cbor.encode(transformedRequest.body); - - const response = await this._fetch( - '' + new URL(`/api/${API_VERSION}/${Endpoint.Read}`, this._host), - { - ...transformedRequest.request, - body, - }, - ); - - if (!response.ok) { - throw new Error( - `Server returned an error:\n` + - ` Code: ${response.status} (${response.statusText}\n)` + - ` Body: ${await response.text()}\n`, - ); - } - - return cbor.decode(Buffer.from(await response.arrayBuffer())); - } -} diff --git a/src/agent/javascript/src/agent/index.ts b/src/agent/javascript/src/agent/index.ts deleted file mode 100644 index 3d0fbaf87f..0000000000 --- a/src/agent/javascript/src/agent/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './api'; -export * from './http'; -export * from './proxy'; diff --git a/src/agent/javascript/src/agent/proxy.ts b/src/agent/javascript/src/agent/proxy.ts deleted file mode 100644 index 0c0b6abf78..0000000000 --- a/src/agent/javascript/src/agent/proxy.ts +++ /dev/null @@ -1,236 +0,0 @@ -import { - ActorFactory, - BinaryBlob, - CallFields, - JsonObject, - Principal, - QueryFields, - QueryResponse, - RequestStatusFields, - RequestStatusResponse, - SubmitResponse, -} from '@dfinity/agent'; -import * as actor from '../actor'; -import * as IDL from '../idl'; -import { Agent } from './api'; - -export enum ProxyMessageKind { - Error = 'err', - Query = 'q', - QueryResponse = 'qr', - Call = 'c', - CallResponse = 'cr', - RequestStatus = 'r', - RequestStatusResponse = 'rr', - Status = 's', - StatusResponse = 'sr', -} - -export interface ProxyMessageBase { - id: number; - type: ProxyMessageKind; -} - -export interface ProxyMessageQuery extends ProxyMessageBase { - type: ProxyMessageKind.Query; - args: [string, QueryFields, Principal | undefined]; -} - -export interface ProxyMessageCall extends ProxyMessageBase { - type: ProxyMessageKind.Call; - args: [string, CallFields, Principal | undefined]; -} - -export interface ProxyMessageRequestStatus extends ProxyMessageBase { - type: ProxyMessageKind.RequestStatus; - args: [RequestStatusFields, Principal | undefined]; -} - -export interface ProxyMessageError extends ProxyMessageBase { - type: ProxyMessageKind.Error; - error: any; -} - -export interface ProxyMessageQueryResponse extends ProxyMessageBase { - type: ProxyMessageKind.QueryResponse; - response: QueryResponse; -} - -export interface ProxyMessageCallResponse extends ProxyMessageBase { - type: ProxyMessageKind.CallResponse; - response: SubmitResponse; -} - -export interface ProxyMessageRequestStatusResponse extends ProxyMessageBase { - type: ProxyMessageKind.RequestStatusResponse; - response: RequestStatusResponse; -} - -export interface ProxyMessageStatus extends ProxyMessageBase { - type: ProxyMessageKind.Status; -} - -export interface ProxyMessageStatusResponse extends ProxyMessageBase { - type: ProxyMessageKind.StatusResponse; - response: JsonObject; -} - -export type ProxyMessage = - | ProxyMessageError - | ProxyMessageQueryResponse - | ProxyMessageCallResponse - | ProxyMessageRequestStatusResponse - | ProxyMessageQuery - | ProxyMessageCall - | ProxyMessageRequestStatus - | ProxyMessageStatus - | ProxyMessageStatusResponse; - -// A Stub Agent that forwards calls to another Agent implementation. -export class ProxyStubAgent { - constructor(private _frontend: (msg: ProxyMessage) => void, private _agent: Agent) {} - - public onmessage(msg: ProxyMessage): void { - switch (msg.type) { - case ProxyMessageKind.Query: - this._agent.query(...msg.args).then(response => { - this._frontend({ - id: msg.id, - type: ProxyMessageKind.QueryResponse, - response, - }); - }); - break; - case ProxyMessageKind.Call: - this._agent.call(...msg.args).then(response => { - this._frontend({ - id: msg.id, - type: ProxyMessageKind.CallResponse, - response, - }); - }); - break; - case ProxyMessageKind.RequestStatus: - this._agent.requestStatus(...msg.args).then(response => { - this._frontend({ - id: msg.id, - type: ProxyMessageKind.RequestStatusResponse, - response, - }); - }); - break; - case ProxyMessageKind.Status: - this._agent.status().then(response => { - this._frontend({ - id: msg.id, - type: ProxyMessageKind.StatusResponse, - response, - }); - }); - break; - - default: - throw new Error(`Invalid message received: ${JSON.stringify(msg)}`); - } - } -} - -// An Agent that forwards calls to a backend. The calls are serialized -export class ProxyAgent implements Agent { - private _nextId = 0; - private _pendingCalls = new Map void, (reject: any) => void]>(); - - constructor(private _backend: (msg: ProxyMessage) => void) {} - - public onmessage(msg: ProxyMessage): void { - const id = msg.id; - - const maybePromise = this._pendingCalls.get(id); - if (!maybePromise) { - throw new Error('A proxy get the same message twice...'); - } - - this._pendingCalls.delete(id); - const [resolve, reject] = maybePromise; - - switch (msg.type) { - case ProxyMessageKind.Error: - return reject(msg.error); - case ProxyMessageKind.CallResponse: - case ProxyMessageKind.QueryResponse: - case ProxyMessageKind.RequestStatusResponse: - return resolve(msg.response); - default: - throw new Error(`Invalid message being sent to ProxyAgent: ${JSON.stringify(msg)}`); - } - } - - public requestStatus( - fields: RequestStatusFields, - principal?: Principal, - ): Promise { - return this._sendAndWait({ - id: this._nextId++, - type: ProxyMessageKind.RequestStatus, - args: [fields, principal], - }) as Promise; - } - - public call( - canisterId: Principal | string, - fields: CallFields, - principal?: Principal, - ): Promise { - return this._sendAndWait({ - id: this._nextId++, - type: ProxyMessageKind.Call, - args: [canisterId.toString(), fields, principal], - }) as Promise; - } - - public createCanister(principal?: Principal): Promise { - throw new Error('unimplemented. This will be removed when we upgrade the spec to 0.8'); - } - - public status(): Promise { - return this._sendAndWait({ - id: this._nextId++, - type: ProxyMessageKind.Status, - }) as Promise; - } - - public install( - canisterId: Principal | string, - fields: { - module: BinaryBlob; - arg?: BinaryBlob; - }, - principal?: Principal, - ): Promise { - throw new Error('unimplemented. This will be removed when we upgrade the spec to 0.8'); - } - - public query( - canisterId: Principal | string, - fields: QueryFields, - principal?: Principal, - ): Promise { - return this._sendAndWait({ - id: this._nextId++, - type: ProxyMessageKind.Query, - args: [canisterId.toString(), fields, principal], - }) as Promise; - } - - public makeActorFactory(actorInterfaceFactory: IDL.InterfaceFactory): ActorFactory { - return actor.makeActorFactory(actorInterfaceFactory); - } - - private async _sendAndWait(msg: ProxyMessage): Promise { - return new Promise((resolve, reject) => { - this._pendingCalls.set(msg.id, [resolve, reject]); - - this._backend(msg); - }); - } -} diff --git a/src/agent/javascript/src/auth.ts b/src/agent/javascript/src/auth.ts deleted file mode 100644 index a457f0f073..0000000000 --- a/src/agent/javascript/src/auth.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Buffer } from 'buffer/'; -import * as tweetnacl from 'tweetnacl'; -import { - AuthHttpAgentRequestTransformFn, - HttpAgentRequest, - SignedHttpAgentRequest, -} from './http_agent_types'; -import { RequestId, requestIdOf } from './request_id'; -import { BinaryBlob } from './types'; - -const domainSeparator = Buffer.from('\x0Aic-request'); - -export type SenderPubKey = BinaryBlob & { __senderPubKey__: void }; -export type SenderSecretKey = BinaryBlob & { __senderSecretKey__: void }; -export type SenderSig = BinaryBlob & { __senderSig__: void }; - -export interface KeyPair { - publicKey: SenderPubKey; - secretKey: SenderSecretKey; -} - -export function sign(requestId: RequestId, secretKey: SenderSecretKey): SenderSig { - const bufA = Buffer.concat([domainSeparator, requestId]); - const signature = tweetnacl.sign.detached(bufA, secretKey); - return Buffer.from(signature) as SenderSig; -} - -export function verify( - requestId: RequestId, - senderSig: SenderSig, - senderPubKey: SenderPubKey, -): boolean { - const bufA = Buffer.concat([domainSeparator, requestId]); - return tweetnacl.sign.detached.verify(bufA, senderSig, senderPubKey); -} - -export const createKeyPairFromSeed = (seed: Uint8Array): KeyPair => { - const { publicKey, secretKey } = tweetnacl.sign.keyPair.fromSeed(seed); - return { - publicKey: Buffer.from(publicKey), - secretKey: Buffer.from(secretKey), - } as KeyPair; -}; - -// TODO/Note/XXX(eftychis): Unused for the first pass. This provides -// us with key generation for the client. -export function generateKeyPair(): KeyPair { - const { publicKey, secretKey } = tweetnacl.sign.keyPair(); - return makeKeyPair(publicKey, secretKey); -} - -export function makeKeyPair(publicKey: Uint8Array, secretKey: Uint8Array): KeyPair { - return { - publicKey: Buffer.from(publicKey), - secretKey: Buffer.from(secretKey), - } as KeyPair; -} - -export type SigningConstructedFn = (requestId: RequestId, secretKey: SenderSecretKey) => SenderSig; - -export function makeAuthTransform( - keyPair: KeyPair, - senderSigFn: SigningConstructedFn = sign, -): AuthHttpAgentRequestTransformFn { - const { publicKey, secretKey } = keyPair; - - const fn = async (r: HttpAgentRequest) => { - const { body, ...fields } = r; - const requestId = await requestIdOf(body); - return { - ...fields, - body: { - content: body, - sender_pubkey: publicKey, - sender_sig: senderSigFn(requestId, secretKey), - }, - } as SignedHttpAgentRequest; - }; - - return fn; -} diff --git a/src/agent/javascript/src/candid/candid-core.ts b/src/agent/javascript/src/candid/candid-core.ts deleted file mode 100644 index 4c7d8c4a94..0000000000 --- a/src/agent/javascript/src/candid/candid-core.ts +++ /dev/null @@ -1,254 +0,0 @@ -import * as IDL from '../idl'; - -// tslint:disable:max-classes-per-file - -export interface ParseConfig { - random?: boolean; -} - -export interface UIConfig { - input?: HTMLElement; - form?: InputForm; - parse(t: IDL.Type, config: ParseConfig, v: string): any; -} - -export interface FormConfig { - open?: HTMLElement; - event?: string; - labelMap?: Record; - container?: HTMLElement; - render(t: IDL.Type): InputBox; -} - -export class InputBox { - public status: HTMLElement; - public label: string | null = null; - public value: any = undefined; - - constructor(public idl: IDL.Type, public ui: UIConfig) { - const status = document.createElement('div'); - status.className = 'status'; - this.status = status; - - if (ui.input) { - ui.input.addEventListener('blur', () => { - if ((ui.input as HTMLInputElement).value === '') { - return; - } - this.parse(); - }); - ui.input.addEventListener('focus', () => { - ui.input!.classList.remove('reject'); - }); - } - } - public isRejected(): boolean { - return this.value === undefined; - } - - public parse(config: ParseConfig = {}): any { - if (this.ui.form) { - const value = this.ui.form.parse(config); - this.value = value; - return value; - } - - if (this.ui.input) { - const input = this.ui.input as HTMLInputElement; - try { - const value = this.ui.parse(this.idl, config, input.value); - if (!this.idl.covariant(value)) { - throw new Error(`${input.value} is not of type ${this.idl.display()}`); - } - this.status.style.display = 'none'; - this.value = value; - return value; - } catch (err) { - input.classList.add('reject'); - this.status.style.display = 'block'; - this.status.innerHTML = 'InputError: ' + err.message; - this.value = undefined; - return undefined; - } - } - return null; - } - public render(dom: HTMLElement): void { - const container = document.createElement('span'); - if (this.label) { - const label = document.createElement('label'); - label.innerText = this.label; - container.appendChild(label); - } - if (this.ui.input) { - container.appendChild(this.ui.input); - container.appendChild(this.status); - } - - if (this.ui.form) { - this.ui.form.render(container); - } - dom.appendChild(container); - } -} - -export abstract class InputForm { - public form: InputBox[] = []; - constructor(public ui: FormConfig) {} - - public abstract parse(config: ParseConfig): any; - public abstract generateForm(): any; - public renderForm(dom: HTMLElement): void { - if (this.ui.container) { - this.form.forEach(e => e.render(this.ui.container!)); - dom.appendChild(this.ui.container); - } else { - this.form.forEach(e => e.render(dom)); - } - } - public render(dom: HTMLElement): void { - if (this.ui.open && this.ui.event) { - dom.appendChild(this.ui.open); - const form = this; - form.ui.open!.addEventListener(form.ui.event!, () => { - // Remove old form - if (form.ui.container) { - form.ui.container.innerHTML = ''; - } else { - const oldContainer = form.ui.open!.nextElementSibling; - if (oldContainer) { - oldContainer.parentNode!.removeChild(oldContainer); - } - } - // Render form - form.generateForm(); - form.renderForm(dom); - }); - } else { - this.generateForm(); - this.renderForm(dom); - } - } -} - -export class RecordForm extends InputForm { - constructor(public fields: Array<[string, IDL.Type]>, public ui: FormConfig) { - super(ui); - } - public generateForm(): void { - this.form = this.fields.map(([key, type]) => { - const input = this.ui.render(type); - if (this.ui.labelMap && this.ui.labelMap.hasOwnProperty(key)) { - input.label = this.ui.labelMap[key] + ' '; - } else { - input.label = key + ' '; - } - return input; - }); - } - public parse(config: ParseConfig): Record | undefined { - const v: Record = {}; - this.fields.forEach(([key, _], i) => { - const value = this.form[i].parse(config); - v[key] = value; - }); - if (this.form.some(input => input.isRejected())) { - return undefined; - } - return v; - } -} - -export class TupleForm extends InputForm { - constructor(public components: IDL.Type[], public ui: FormConfig) { - super(ui); - } - public generateForm(): void { - this.form = this.components.map(type => { - const input = this.ui.render(type); - return input; - }); - } - public parse(config: ParseConfig): any[] | undefined { - const v: any[] = []; - this.components.forEach((_, i) => { - const value = this.form[i].parse(config); - v.push(value); - }); - if (this.form.some(input => input.isRejected())) { - return undefined; - } - return v; - } -} - -export class VariantForm extends InputForm { - constructor(public fields: Array<[string, IDL.Type]>, public ui: FormConfig) { - super(ui); - } - public generateForm(): void { - const index = (this.ui.open as HTMLSelectElement).selectedIndex; - const [_, type] = this.fields[index]; - const variant = this.ui.render(type); - this.form = [variant]; - } - public parse(config: ParseConfig): Record | undefined { - const select = this.ui.open as HTMLSelectElement; - const selected = select.options[select.selectedIndex].value; - const value = this.form[0].parse(config); - if (value === undefined) { - return undefined; - } - const v: Record = {}; - v[selected] = value; - return v; - } -} - -export class OptionForm extends InputForm { - constructor(public ty: IDL.Type, public ui: FormConfig) { - super(ui); - } - public generateForm(): void { - if ((this.ui.open as HTMLInputElement).checked) { - const opt = this.ui.render(this.ty); - this.form = [opt]; - } else { - this.form = []; - } - } - public parse(config: ParseConfig): [T] | [] | undefined { - if (this.form.length === 0) { - return []; - } else { - const value = this.form[0].parse(config); - if (value === undefined) { - return undefined; - } - return [value]; - } - } -} - -export class VecForm extends InputForm { - constructor(public ty: IDL.Type, public ui: FormConfig) { - super(ui); - } - public generateForm(): void { - const len = +(this.ui.open as HTMLInputElement).value; - this.form = []; - for (let i = 0; i < len; i++) { - const t = this.ui.render(this.ty); - this.form.push(t); - } - } - public parse(config: ParseConfig): T[] | undefined { - const value = this.form.map(input => { - return input.parse(config); - }); - if (this.form.some(input => input.isRejected())) { - return undefined; - } - return value; - } -} diff --git a/src/agent/javascript/src/candid/candid-ui.ts b/src/agent/javascript/src/candid/candid-ui.ts deleted file mode 100644 index 8a1d64ac7f..0000000000 --- a/src/agent/javascript/src/candid/candid-ui.ts +++ /dev/null @@ -1,248 +0,0 @@ -import BigNumber from 'bignumber.js'; -import * as IDL from '../idl'; -import { Principal } from '../principal'; -import * as UI from './candid-core'; - -// tslint:disable:max-classes-per-file -type InputBox = UI.InputBox; - -const InputConfig: UI.UIConfig = { parse: parsePrimitive }; -const FormConfig: UI.FormConfig = { render: renderInput }; - -export const inputBox = (t: IDL.Type, config: Partial) => { - return new UI.InputBox(t, { ...InputConfig, ...config }); -}; -export const recordForm = (fields: Array<[string, IDL.Type]>, config: Partial) => { - return new UI.RecordForm(fields, { ...FormConfig, ...config }); -}; -export const tupleForm = (components: IDL.Type[], config: Partial) => { - return new UI.TupleForm(components, { ...FormConfig, ...config }); -}; -export const variantForm = (fields: Array<[string, IDL.Type]>, config: Partial) => { - return new UI.VariantForm(fields, { ...FormConfig, ...config }); -}; -export const optForm = (ty: IDL.Type, config: Partial) => { - return new UI.OptionForm(ty, { ...FormConfig, ...config }); -}; -export const vecForm = (ty: IDL.Type, config: Partial) => { - return new UI.VecForm(ty, { ...FormConfig, ...config }); -}; - -export class Render extends IDL.Visitor { - public visitType(t: IDL.Type, d: null): InputBox { - const input = document.createElement('input'); - input.classList.add('argument'); - input.placeholder = t.display(); - return inputBox(t, { input }); - } - public visitNull(t: IDL.NullClass, d: null): InputBox { - return inputBox(t, {}); - } - public visitRecord(t: IDL.RecordClass, fields: Array<[string, IDL.Type]>, d: null): InputBox { - let config = {}; - if (fields.length > 1) { - const container = document.createElement('div'); - container.classList.add('popup-form'); - config = { container }; - } - const form = recordForm(fields, config); - return inputBox(t, { form }); - } - public visitTuple( - t: IDL.TupleClass, - components: IDL.Type[], - d: null, - ): InputBox { - let config = {}; - if (components.length > 1) { - const container = document.createElement('div'); - container.classList.add('popup-form'); - config = { container }; - } - const form = tupleForm(components, config); - return inputBox(t, { form }); - } - public visitVariant(t: IDL.VariantClass, fields: Array<[string, IDL.Type]>, d: null): InputBox { - const select = document.createElement('select'); - for (const [key, type] of fields) { - const option = new Option(key); - select.add(option); - } - select.selectedIndex = -1; - select.classList.add('open'); - const config: Partial = { open: select, event: 'change' }; - const form = variantForm(fields, config); - return inputBox(t, { form }); - } - public visitOpt(t: IDL.OptClass, ty: IDL.Type, d: null): InputBox { - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.classList.add('open'); - const form = optForm(ty, { open: checkbox, event: 'change' }); - return inputBox(t, { form }); - } - public visitVec(t: IDL.VecClass, ty: IDL.Type, d: null): InputBox { - const len = document.createElement('input'); - len.type = 'number'; - len.min = '0'; - len.max = '100'; - len.style.width = '3em'; - len.placeholder = 'len'; - len.classList.add('open'); - const container = document.createElement('div'); - container.classList.add('popup-form'); - const form = vecForm(ty, { open: len, event: 'change', container }); - return inputBox(t, { form }); - } - public visitRec(t: IDL.RecClass, ty: IDL.ConstructType, d: null): InputBox { - return renderInput(ty); - } -} - -class Parse extends IDL.Visitor { - public visitNull(t: IDL.NullClass, v: string): null { - return null; - } - public visitBool(t: IDL.BoolClass, v: string): boolean { - if (v === 'true') { - return true; - } - if (v === 'false') { - return false; - } - throw new Error(`Cannot parse ${v} as boolean`); - } - public visitText(t: IDL.TextClass, v: string): string { - return v; - } - public visitFloat(t: IDL.FloatClass, v: string): number { - return parseFloat(v); - } - public visitNumber(t: IDL.PrimitiveType, v: string): BigNumber { - return new BigNumber(v); - } - public visitPrincipal(t: IDL.PrincipalClass, v: string): Principal { - return Principal.fromText(v); - } - public visitService(t: IDL.ServiceClass, v: string): Principal { - return Principal.fromText(v); - } - public visitFunc(t: IDL.FuncClass, v: string): [Principal, string] { - const x = v.split('.', 2); - return [Principal.fromText(x[0]), x[1]]; - } -} - -class Random extends IDL.Visitor { - public visitNull(t: IDL.NullClass, v: string): null { - return null; - } - public visitBool(t: IDL.BoolClass, v: string): boolean { - return Math.random() < 0.5; - } - public visitText(t: IDL.TextClass, v: string): string { - return Math.random().toString(36).substring(6); - } - public visitFloat(t: IDL.FloatClass, v: string): number { - return Math.random(); - } - public visitInt(t: IDL.IntClass, v: string): BigNumber { - return new BigNumber(this.generateNumber(true)); - } - public visitNat(t: IDL.NatClass, v: string): BigNumber { - return new BigNumber(this.generateNumber(false)); - } - public visitFixedInt(t: IDL.FixedIntClass, v: string): BigNumber { - return new BigNumber(this.generateNumber(true)); - } - public visitFixedNat(t: IDL.FixedNatClass, v: string): BigNumber { - return new BigNumber(this.generateNumber(false)); - } - private generateNumber(signed: boolean): number { - const num = Math.floor(Math.random() * 100); - if (signed && Math.random() < 0.5) { - return -num; - } else { - return num; - } - } -} - -function parsePrimitive(t: IDL.Type, config: UI.ParseConfig, d: string) { - if (config.random && d === '') { - return t.accept(new Random(), d); - } else { - return t.accept(new Parse(), d); - } -} - -export function renderInput(t: IDL.Type): InputBox { - return t.accept(new Render(), null); -} - -interface ValueConfig { - input: InputBox; - value: any; -} - -export function renderValue(t: IDL.Type, input: InputBox, value: any) { - return t.accept(new RenderValue(), { input, value }); -} - -class RenderValue extends IDL.Visitor { - public visitType(t: IDL.Type, d: ValueConfig) { - (d.input.ui.input as HTMLInputElement).value = t.valueToString(d.value); - } - public visitNull(t: IDL.NullClass, d: ValueConfig) {} - public visitText(t: IDL.TextClass, d: ValueConfig) { - (d.input.ui.input as HTMLInputElement).value = d.value; - } - public visitRec(t: IDL.RecClass, ty: IDL.ConstructType, d: ValueConfig) { - renderValue(ty, d.input, d.value); - } - public visitOpt(t: IDL.OptClass, ty: IDL.Type, d: ValueConfig) { - if (d.value.length === 0) { - return; - } else { - const form = d.input.ui.form!; - const open = form.ui.open as HTMLInputElement; - open.checked = true; - open.dispatchEvent(new Event(form.ui.event!)); - renderValue(ty, form.form[0], d.value[0]); - } - } - public visitRecord(t: IDL.RecordClass, fields: Array<[string, IDL.Type]>, d: ValueConfig) { - const form = d.input.ui.form!; - fields.forEach(([key, type], i) => { - renderValue(type, form.form[i], d.value[key]); - }); - } - public visitTuple(t: IDL.TupleClass, components: IDL.Type[], d: ValueConfig) { - const form = d.input.ui.form!; - components.forEach((type, i) => { - renderValue(type, form.form[i], d.value[i]); - }); - } - public visitVariant(t: IDL.VariantClass, fields: Array<[string, IDL.Type]>, d: ValueConfig) { - const form = d.input.ui.form!; - const selected = Object.entries(d.value)[0]; - fields.forEach(([key, type], i) => { - if (key === selected[0]) { - const open = form.ui.open as HTMLSelectElement; - open.selectedIndex = i; - open.dispatchEvent(new Event(form.ui.event!)); - renderValue(type, form.form[0], selected[1]); - } - }); - } - public visitVec(t: IDL.VecClass, ty: IDL.Type, d: ValueConfig) { - const form = d.input.ui.form!; - const len = d.value.length; - const open = form.ui.open as HTMLInputElement; - open.value = len; - open.dispatchEvent(new Event(form.ui.event!)); - d.value.forEach((v: T, i: number) => { - renderValue(ty, form.form[i], v); - }); - } -} diff --git a/src/agent/javascript/src/candid/index.ts b/src/agent/javascript/src/candid/index.ts deleted file mode 100644 index bf9b965b94..0000000000 --- a/src/agent/javascript/src/candid/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './candid-ui'; -export * from './candid-core'; diff --git a/src/agent/javascript/src/canisters/asset.ts b/src/agent/javascript/src/canisters/asset.ts deleted file mode 100644 index d4dc6754fa..0000000000 --- a/src/agent/javascript/src/canisters/asset.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Actor, ActorConfig, ActorSubclass, CallConfig } from '../actor'; -import assetCanister from './asset_idl'; - -/* tslint:disable */ -export interface AssetCanisterRecord { - store(path: string, content: number[]): Promise; - retrieve(path: string): Promise; -} -/* tslint:enable */ - -/** - * Create a management canister actor. - * @param config - */ -export function createAssetCanisterActor(config: ActorConfig) { - return Actor.createActor(assetCanister, config); -} diff --git a/src/agent/javascript/src/canisters/asset_idl.ts b/src/agent/javascript/src/canisters/asset_idl.ts deleted file mode 100644 index a698ae31dd..0000000000 --- a/src/agent/javascript/src/canisters/asset_idl.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * This file is generated from the candid for asset management. - */ -/* tslint:disable */ -// @ts-ignore -export default ({ IDL }) => { - return IDL.Service({ - retrieve: IDL.Func([IDL.Text], [IDL.Vec(IDL.Nat8)], ['query']), - store: IDL.Func([IDL.Text, IDL.Vec(IDL.Nat8)], [], []), - }); -}; diff --git a/src/agent/javascript/src/canisters/management.ts b/src/agent/javascript/src/canisters/management.ts deleted file mode 100644 index 5b581c36eb..0000000000 --- a/src/agent/javascript/src/canisters/management.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Actor, CallConfig } from '../actor'; -import { Principal } from '../principal'; -import managementCanisterIdl from './management_idl'; - -/* tslint:disable */ -export interface ManagementCanisterRecord { - create_canister(): Promise<{ canister_id: Principal }>; - install_code(arg0: { - mode: { install: null } | { reinstall: null } | { upgrade: null }; - canister_id: Principal; - wasm_module: number[]; - arg: number[]; - compute_allocation: [] | [number]; - memory_allocation: [] | [number]; - }): Promise; -} -/* tslint:enable */ - -/** - * Create a management canister actor. - * @param config - */ -export function getManagementCanister(config: CallConfig) { - return Actor.createActor(managementCanisterIdl, { - ...config, - canisterId: Principal.fromHex(''), - }); -} diff --git a/src/agent/javascript/src/canisters/management_idl.ts b/src/agent/javascript/src/canisters/management_idl.ts deleted file mode 100644 index d394170681..0000000000 --- a/src/agent/javascript/src/canisters/management_idl.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * This file is generated from the candid for asset management. - */ -/* tslint:disable */ -// @ts-ignore -export default ({ IDL }) => { - const canister_id = IDL.Principal; - const wasm_module = IDL.Vec(IDL.Nat8); - return IDL.Service({ - create_canister: IDL.Func([], [IDL.Record({ canister_id: canister_id })], []), - install_code: IDL.Func( - [ - IDL.Record({ - mode: IDL.Variant({ install: IDL.Null, reinstall: IDL.Null, upgrade: IDL.Null }), - canister_id: canister_id, - wasm_module: wasm_module, - arg: IDL.Vec(IDL.Nat8), - compute_allocation: IDL.Opt(IDL.Nat), - memory_allocation: IDL.Opt(IDL.Nat), - }), - ], - [], - [], - ), - set_controller: IDL.Func( - [IDL.Record({ canister_id: canister_id, new_controller: IDL.Principal })], - [], - [], - ), - }); -}; diff --git a/src/agent/javascript/src/cbor.test.ts b/src/agent/javascript/src/cbor.test.ts deleted file mode 100644 index b642e11d30..0000000000 --- a/src/agent/javascript/src/cbor.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import BigNumber from 'bignumber.js'; -import { Buffer } from 'buffer/'; -import { decode, encode } from './cbor'; -import { Principal } from './principal'; -import { BinaryBlob, blobFromHex, blobFromUint8Array, blobToHex } from './types'; - -test('round trip', () => { - interface Data { - a: number; - b: string; - c: BinaryBlob; - d: { four: string }; - e: Principal; - f: BinaryBlob; - g: BigNumber; - } - - // FIXME: since we have limited control over CBOR decoding, we are relying on - // BigNumber types actually containing big numbers, since small numbers are - // represented as numbers and big numbers are represented as strings. - const input: Data = { - a: 1, - b: 'two', - c: Buffer.from([3]) as BinaryBlob, - d: { four: 'four' }, - e: Principal.fromText('ic:FfFfFfFfFfFfFfFfd7'), - f: Buffer.from([]) as BinaryBlob, - g: new BigNumber('0xffffffffffffffff'), - }; - - const output = decode(encode(input)); - - // Some values don't decode exactly to the value that was encoded, - // but their hexadecimal representions are the same. - const { c: inputC, e: inputE, f: inputF, ...inputRest } = input; - - const { c: outputC, e: outputE, f: outputF, ...outputRest } = output; - - expect(blobToHex(outputC)).toBe(blobToHex(inputC)); - expect(buf2hex((outputE as any) as Uint8Array).toUpperCase()).toBe(inputE.toHex()); - expect(outputRest).toEqual(inputRest); -}); - -test('empty canister ID', () => { - const input: { a: Principal } = { - a: Principal.fromText('aaaaa-aa'), - }; - - const output = decode(encode(input)); - - const inputA = input.a; - const outputA = output.a; - - expect(buf2hex((outputA as any) as Uint8Array)).toBe(inputA.toHex()); - expect(Principal.fromBlob(outputA as any).toText()).toBe('aaaaa-aa'); -}); - -function buf2hex(buffer: Uint8Array) { - // Construct an array such that each number is translated to the - // hexadecimal equivalent, ensure it is a string and padded then - // join the elements. - return Array.prototype.map.call(buffer, x => ('00' + x.toString(16)).slice(-2)).join(''); -} diff --git a/src/agent/javascript/src/cbor.ts b/src/agent/javascript/src/cbor.ts deleted file mode 100644 index 1517786f01..0000000000 --- a/src/agent/javascript/src/cbor.ts +++ /dev/null @@ -1,80 +0,0 @@ -// tslint:disable:max-classes-per-file -// This file is based on: -// tslint:disable-next-line: max-line-length -// https://github.com/dfinity-lab/dfinity/blob/9bca65f8edd65701ea6bdb00e0752f9186bbc893/docs/spec/public/index.adoc#cbor-encoding-of-requests-and-responses -import borc from 'borc'; -import { Buffer } from 'buffer/'; -import * as cbor from 'simple-cbor'; -import { CborEncoder, SelfDescribeCborSerializer } from 'simple-cbor'; -import { Principal } from './principal'; -import { BinaryBlob } from './types'; - -// We are using hansl/simple-cbor for CBOR serialization, to avoid issues with -// encoding the uint64 values that the HTTP handler of the client expects for -// canister IDs. However, simple-cbor does not yet provide deserialization so -// we are using `BigNumber` and `Buffer` types instead of `BigInt` and -// `Uint8Array` (respectively) so that we can use the dignifiedquire/borc CBOR -// decoder. - -class PrincipalEncoder implements CborEncoder { - public get name() { - return 'Principal'; - } - - public get priority() { - return 0; - } - - public match(value: any): boolean { - return value && value._isPrincipal === true; - } - - public encode(v: Principal): cbor.CborValue { - return cbor.value.bytes(v.toBlob()); - } -} - -class BufferEncoder implements CborEncoder { - public get name() { - return 'Buffer'; - } - - public get priority() { - return 1; - } - - public match(value: any): boolean { - return Buffer.isBuffer(value); - } - - public encode(v: Buffer): cbor.CborValue { - return cbor.value.bytes(new Uint8Array(v)); - } -} - -const serializer = SelfDescribeCborSerializer.withDefaultEncoders(true); -serializer.addEncoder(new PrincipalEncoder()); -serializer.addEncoder(new BufferEncoder()); - -export enum CborTag { - Uint64LittleEndian = 71, - Semantic = 55799, -} - -export const encode = (value: any): BinaryBlob => { - return Buffer.from(serializer.serialize(value)) as BinaryBlob; -}; - -export function decode(input: Uint8Array): T { - const decoder = new borc.Decoder({ - size: input.byteLength, - tags: { - [CborTag.Semantic]: (value: T): T => value, - }, - }); - const result = decoder.decodeFirst(input); - if (result.hasOwnProperty('canister_id')) { - result.canister_id = Principal.fromText(result.canister_id.toString(16)); - } - return result; -} diff --git a/src/agent/javascript/src/http_agent.test.ts b/src/agent/javascript/src/http_agent.test.ts deleted file mode 100644 index 926641e3f6..0000000000 --- a/src/agent/javascript/src/http_agent.test.ts +++ /dev/null @@ -1,243 +0,0 @@ -import { Buffer } from 'buffer/'; -import { HttpAgent } from './agent'; -import { createKeyPairFromSeed, makeAuthTransform, SenderSig, sign, verify } from './auth'; -import * as cbor from './cbor'; -import { makeNonceTransform } from './http_agent_transforms'; -import { - CallRequest, - ReadRequestType, - RequestStatusResponseReplied, - Signed, - SubmitRequestType, -} from './http_agent_types'; -import { Principal } from './principal'; -import { requestIdOf } from './request_id'; -import { BinaryBlob } from './types'; -import { Nonce } from './types'; - -test('call', async () => { - const mockFetch: jest.Mock = jest.fn((resource, init) => { - return Promise.resolve( - new Response(null, { - status: 200, - }), - ); - }); - - const canisterId: Principal = Principal.fromText('2chl6-4hpzw-vqaaa-aaaaa-c'); - const nonce = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7]) as Nonce; - // prettier-ignore - const seed = Buffer.from([ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - ]); - const keyPair = createKeyPairFromSeed(seed); - const principal = await Principal.selfAuthenticating(keyPair.publicKey); - - const httpAgent = new HttpAgent({ - fetch: mockFetch, - principal, - }); - httpAgent.addTransform(makeNonceTransform(() => nonce)); - httpAgent.setAuthTransform(makeAuthTransform(keyPair)); - - const methodName = 'greet'; - const arg = Buffer.from([]) as BinaryBlob; - - const { requestId } = await httpAgent.call(canisterId, { - methodName, - arg, - }); - - const mockPartialRequest = { - request_type: SubmitRequestType.Call, - canister_id: canisterId, - method_name: methodName, - // We need a request id for the signature and at the same time we - // are checking that signature does not impact the request id. - arg, - nonce, - sender: principal.toBlob(), - }; - - const mockPartialsRequestId = await requestIdOf(mockPartialRequest); - const senderSig = sign(mockPartialsRequestId, keyPair.secretKey); - // Just sanity checking our life. - expect(verify(mockPartialsRequestId, senderSig, keyPair.publicKey)).toBe(true); - - const expectedRequest: Signed = { - content: mockPartialRequest, - sender_pubkey: keyPair.publicKey, - sender_sig: senderSig, - } as Signed; - - const expectedRequestId = await requestIdOf(expectedRequest.content); - expect(expectedRequestId).toEqual(mockPartialsRequestId); - - const { calls, results } = mockFetch.mock; - expect(calls.length).toBe(1); - expect(requestId).toEqual(expectedRequestId); - - expect(calls[0][0]).toBe('http://localhost/api/v1/submit'); - expect(calls[0][1]).toEqual({ - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - }, - body: cbor.encode(expectedRequest), - }); -}); - -test.todo('query'); - -test('requestStatus', async () => { - const mockResponse = { - status: 'replied', - reply: { arg: Buffer.from([]) as BinaryBlob }, - }; - - const mockFetch: jest.Mock = jest.fn((resource, init) => { - const body = cbor.encode(mockResponse); - return Promise.resolve( - new Response(body, { - status: 200, - }), - ); - }); - - const canisterIdent = '2chl6-4hpzw-vqaaa-aaaaa-c'; - const nonce = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7]) as Nonce; - - // prettier-ignore - const seed = Buffer.from([ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - ]); - const keyPair = createKeyPairFromSeed(seed); - const senderPubKey = keyPair.publicKey; - const principal = await Principal.selfAuthenticating(senderPubKey); - - const httpAgent = new HttpAgent({ - fetch: mockFetch, - principal, - }); - httpAgent.addTransform(makeNonceTransform(() => nonce)); - httpAgent.setAuthTransform(makeAuthTransform(keyPair, () => Buffer.from([0]) as SenderSig)); - - const requestId = await requestIdOf({ - request_type: SubmitRequestType.Call, - nonce, - canister_id: Principal.fromText(canisterIdent), - method_name: 'greet', - arg: Buffer.from([]), - sender: principal.toBlob(), - }); - - const response = await httpAgent.requestStatus({ - requestId, - }); - - const expectedRequest = { - content: { - request_type: ReadRequestType.RequestStatus, - request_id: requestId, - }, - sender_pubkey: senderPubKey, - sender_sig: Buffer.from([0]) as SenderSig, - }; - - const { calls, results } = mockFetch.mock; - expect(calls.length).toBe(1); - - // Trick the type system. - const { - reply: { arg: responseArg }, - ...responseRest - } = response as RequestStatusResponseReplied; - - const { - reply: { arg: mockResponseArg }, - ...mockResponseRest - } = mockResponse; - - expect(responseRest).toEqual(mockResponseRest); - expect(responseArg?.equals(mockResponseArg)).toBe(true); - - expect(calls[0]).toEqual([ - 'http://localhost/api/v1/read', - { - method: 'POST', - headers: { - 'Content-Type': 'application/cbor', - }, - body: cbor.encode(expectedRequest), - }, - ]); -}); - -test('queries with the same content should have the same signature', async () => { - const mockResponse = { - status: 'replied', - reply: { arg: Buffer.from([]) as BinaryBlob }, - }; - - const mockFetch: jest.Mock = jest.fn((resource, init) => { - const body = cbor.encode(mockResponse); - return Promise.resolve( - new Response(body, { - status: 200, - }), - ); - }); - - const canisterIdent = '2chl6-4hpzw-vqaaa-aaaaa-c'; - const nonce = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7]) as Nonce; - - // prettier-ignore - const seed = Buffer.from([ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - ]); - const keyPair = createKeyPairFromSeed(seed); - const senderPubKey = keyPair.publicKey; - const principal = await Principal.selfAuthenticating(senderPubKey); - - const httpAgent = new HttpAgent({ - fetch: mockFetch, - principal, - }); - httpAgent.addTransform(makeNonceTransform(() => nonce)); - httpAgent.setAuthTransform(makeAuthTransform(keyPair)); - - const methodName = 'greet'; - const arg = Buffer.from([]) as BinaryBlob; - - const requestId = await requestIdOf({ - request_type: SubmitRequestType.Call, - nonce, - canister_id: Principal.fromText(canisterIdent), - method_name: methodName, - arg, - sender: principal.toBlob(), - }); - - const response1 = await httpAgent.requestStatus({ - requestId, - }); - - const response2 = await httpAgent.requestStatus({ - requestId, - }); - - const response3 = await httpAgent.query(canisterIdent, { arg, methodName }); - const response4 = await httpAgent.query(canisterIdent, { methodName, arg }); - - const { calls } = mockFetch.mock; - expect(calls.length).toBe(4); - - expect(calls[0]).toEqual(calls[1]); - expect(response1).toEqual(response2); - - expect(calls[2]).toEqual(calls[3]); - expect(response3).toEqual(response4); -}); diff --git a/src/agent/javascript/src/http_agent_transforms.ts b/src/agent/javascript/src/http_agent_transforms.ts deleted file mode 100644 index 0ed57b53d9..0000000000 --- a/src/agent/javascript/src/http_agent_transforms.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Endpoint, HttpAgentRequest, HttpAgentRequestTransformFn } from './http_agent_types'; -import { makeNonce, Nonce } from './types'; - -export function makeNonceTransform(nonceFn: () => Nonce = makeNonce): HttpAgentRequestTransformFn { - return async (request: HttpAgentRequest) => { - if (request.endpoint !== Endpoint.Read) { - request.body.nonce = nonceFn(); - } - }; -} diff --git a/src/agent/javascript/src/http_agent_types.ts b/src/agent/javascript/src/http_agent_types.ts deleted file mode 100644 index cb296f0547..0000000000 --- a/src/agent/javascript/src/http_agent_types.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { Principal } from './principal'; -import { RejectCode } from './reject_code'; -import { RequestId } from './request_id'; -import { BinaryBlob } from './types'; - -export const enum Endpoint { - Read = 'read', - Submit = 'submit', - Status = 'status', -} - -// An HttpAgent request, before it gets encoded and sent to the server. -// We create an empty request that we will fill later. -export type HttpAgentRequest = HttpAgentReadRequest | HttpAgentSubmitRequest; - -export interface HttpAgentBaseRequest { - readonly endpoint: Endpoint; - request: RequestInit; -} - -export interface HttpAgentSubmitRequest extends HttpAgentBaseRequest { - readonly endpoint: Endpoint.Submit; - body: SubmitRequest; -} - -export interface HttpAgentReadRequest extends HttpAgentBaseRequest { - readonly endpoint: Endpoint.Read; - body: ReadRequest; -} - -export type SignedHttpAgentRequest = SignedHttpAgentReadRequest | SignedHttpAgentSubmitRequest; - -export interface SignedHttpAgentSubmitRequest extends HttpAgentBaseRequest { - readonly endpoint: Endpoint.Submit; - body: Signed; -} - -export interface SignedHttpAgentReadRequest extends HttpAgentBaseRequest { - readonly endpoint: Endpoint.Read; - body: Signed; -} - -export interface Signed { - content: T; - sender_pubkey: BinaryBlob; - sender_sig: BinaryBlob; -} - -export interface HttpAgentRequestTransformFn { - (args: HttpAgentRequest): Promise; - priority?: number; -} - -export type AuthHttpAgentRequestTransformFn = ( - args: HttpAgentRequest, -) => Promise; - -export interface QueryFields { - methodName: string; - arg: BinaryBlob; -} -export interface RequestStatusFields { - requestId: RequestId; -} - -export interface CallFields { - methodName: string; - arg: BinaryBlob; -} - -// The fields in a "call" submit request. -// tslint:disable:camel-case -export interface CallRequest extends Record { - request_type: SubmitRequestType.Call; - canister_id: Principal; - method_name: string; - arg: BinaryBlob; - sender: BinaryBlob; -} -export interface InstallCodeRequest extends Record { - request_type: SubmitRequestType.InstallCode; - canister_id: Principal; - module: BinaryBlob; - arg?: BinaryBlob; - sender: BinaryBlob; -} -export interface CreateCanisterRequest extends Record { - request_type: SubmitRequestType.CreateCanister; - sender: BinaryBlob; -} -// tslint:enable:camel-case - -// The types of values allowed in the `request_type` field for submit requests. -export enum SubmitRequestType { - Call = 'call', - InstallCode = 'install_code', - CreateCanister = 'create_canister', -} - -export type SubmitRequest = CallRequest | InstallCodeRequest | CreateCanisterRequest; -export interface SubmitResponse { - requestId: RequestId; - response: { - ok: boolean; - status: number; - statusText: string; - }; -} - -// An ADT that represents responses to a "query" read request. -export type QueryResponse = QueryResponseReplied | QueryResponseRejected; - -export interface QueryResponseBase { - status: QueryResponseStatus; -} - -export interface QueryResponseReplied extends QueryResponseBase { - status: QueryResponseStatus.Replied; - reply: { arg: BinaryBlob }; -} - -export interface QueryResponseRejected extends QueryResponseBase { - status: QueryResponseStatus.Rejected; - reject_code: RejectCode; - reject_message: string; -} - -export const enum QueryResponseStatus { - Replied = 'replied', - Rejected = 'rejected', -} - -// The types of values allowed in the `request_type` field for read requests. -export const enum ReadRequestType { - Query = 'query', - RequestStatus = 'request_status', -} - -// The fields in a "query" read request. -export interface QueryRequest extends Record { - request_type: ReadRequestType.Query; - canister_id: Principal; - method_name: string; - arg: BinaryBlob; - sender: BinaryBlob; -} - -// The fields in a "request_status" read request. -export interface RequestStatusRequest extends Record { - request_type: ReadRequestType.RequestStatus; - request_id: RequestId; -} - -// An ADT that represents responses to a "request_status" read request. -export type RequestStatusResponse = - | RequestStatusResponseReceived - | RequestStatusResponseProcessing - | RequestStatusResponseReplied - | RequestStatusResponseRejected - | RequestStatusResponseUnknown; - -export interface RequestStatusResponseReceived { - status: RequestStatusResponseStatus.Received; -} - -export interface RequestStatusResponseProcessing { - status: RequestStatusResponseStatus.Processing; -} - -export interface RequestStatusResponseReplied { - status: RequestStatusResponseStatus.Replied; - reply: { - canister_id?: BinaryBlob; - arg?: BinaryBlob; - }; -} - -export interface RequestStatusResponseRejected { - status: RequestStatusResponseStatus.Rejected; - reject_code: RejectCode; - reject_message: string; -} - -export interface RequestStatusResponseUnknown { - status: RequestStatusResponseStatus.Unknown; -} - -export enum RequestStatusResponseStatus { - Received = 'received', - Processing = 'processing', - Replied = 'replied', - Rejected = 'rejected', - Unknown = 'unknown', -} - -export type ReadRequest = QueryRequest | RequestStatusRequest; -export type ReadResponse = QueryResponse | RequestStatusResponse; diff --git a/src/agent/javascript/src/idl.test.ts b/src/agent/javascript/src/idl.test.ts deleted file mode 100644 index bbd79decc0..0000000000 --- a/src/agent/javascript/src/idl.test.ts +++ /dev/null @@ -1,416 +0,0 @@ -// tslint:disable -import BigNumber from 'bignumber.js'; -import * as IDL from './idl'; -import { Buffer } from 'buffer/'; -import { Principal } from './principal'; - -function testEncode(typ: IDL.Type, val: any, hex: string, _str: string) { - expect(IDL.encode([typ], [val]).toString('hex')).toEqual(hex); -} - -function testDecode(typ: IDL.Type, val: any, hex: string, _str: string) { - expect(IDL.decode([typ], Buffer.from(hex, 'hex'))[0]).toEqual(val); -} - -function test_(typ: IDL.Type, val: any, hex: string, str: string) { - testEncode(typ, val, hex, str); - testDecode(typ, val, hex, str); -} - -function test_args(typs: IDL.Type[], vals: any[], hex: string, _str: string) { - expect(IDL.encode(typs, vals)).toEqual(Buffer.from(hex, 'hex')); - expect(IDL.decode(typs, Buffer.from(hex, 'hex'))).toEqual(vals); -} - -test('IDL encoding (magic number)', () => { - // Wrong magic number - expect(() => IDL.decode([IDL.Nat], Buffer.from('2a'))).toThrow( - /Message length smaller than magic number/, - ); - expect(() => IDL.decode([IDL.Nat], Buffer.from('4449444d2a'))).toThrow(/Wrong magic number:/); -}); - -test('IDL encoding (empty)', () => { - // Empty - expect(() => IDL.encode([IDL.Empty], [undefined])).toThrow(/Invalid empty argument:/); - expect(() => IDL.decode([IDL.Empty], Buffer.from('4449444c00016f', 'hex'))).toThrow( - /Empty cannot appear as an output/, - ); -}); - -test('IDL encoding (null)', () => { - // Null - test_(IDL.Null, null, '4449444c00017f', 'Null value'); -}); - -test('IDL encoding (text)', () => { - // Text - test_(IDL.Text, 'Hi ☃\n', '4449444c00017107486920e298830a', 'Text with unicode'); - test_( - IDL.Opt(IDL.Text), - ['Hi ☃\n'], - '4449444c016e7101000107486920e298830a', - 'Nested text with unicode', - ); - expect(() => IDL.encode([IDL.Text], [0])).toThrow(/Invalid text argument/); - expect(() => IDL.encode([IDL.Text], [null])).toThrow(/Invalid text argument/); - expect(() => - IDL.decode([IDL.Vec(IDL.Nat8)], Buffer.from('4449444c00017107486920e298830a', 'hex')), - ).toThrow(/type mismatch: type on the wire text, expect type vec nat8/); -}); - -test('IDL encoding (int)', () => { - // Int - test_(IDL.Int, new BigNumber(0), '4449444c00017c00', 'Int'); - test_(IDL.Int, new BigNumber(42), '4449444c00017c2a', 'Int'); - test_(IDL.Int, new BigNumber(1234567890), '4449444c00017cd285d8cc04', 'Positive Int'); - test_( - IDL.Int, - new BigNumber('60000000000000000'), - '4449444c00017c808098f4e9b5caea00', - 'Positive BigInt', - ); - test_(IDL.Int, new BigNumber(-1234567890), '4449444c00017caefaa7b37b', 'Negative Int'); - test_(IDL.Opt(IDL.Int), [new BigNumber(42)], '4449444c016e7c0100012a', 'Nested Int'); - testEncode(IDL.Opt(IDL.Int), [42], '4449444c016e7c0100012a', 'Nested Int (number)'); - expect(() => IDL.decode([IDL.Int], Buffer.from('4449444c00017d2a', 'hex'))).toThrow( - /type mismatch: type on the wire nat, expect type int/, - ); -}); - -test('IDL encoding (nat)', () => { - // Nat - test_(IDL.Nat, new BigNumber(42), '4449444c00017d2a', 'Nat'); - test_(IDL.Nat, new BigNumber(1234567890), '4449444c00017dd285d8cc04', 'Positive Nat'); - test_( - IDL.Nat, - new BigNumber('60000000000000000'), - '4449444c00017d808098f4e9b5ca6a', - 'Positive BigInt', - ); - testEncode(IDL.Opt(IDL.Nat), [42], '4449444c016e7d0100012a', 'Nested Nat (number)'); - expect(() => IDL.encode([IDL.Nat], [-1])).toThrow(/Invalid nat argument/); -}); - -test('IDL encoding (float64)', () => { - // Float64 - test_(IDL.Float64, 3, '4449444c0001720000000000000840', 'Float'); - test_(IDL.Float64, 6, '4449444c0001720000000000001840', 'Float'); - test_(IDL.Float64, 0.5, '4449444c000172000000000000e03f', 'Float'); - test_(IDL.Float64, Number.NaN, '4449444c000172010000000000f07f', 'NaN'); - test_(IDL.Float64, Number.POSITIVE_INFINITY, '4449444c000172000000000000f07f', '+infinity'); - test_(IDL.Float64, Number.NEGATIVE_INFINITY, '4449444c000172000000000000f0ff', '-infinity'); - test_(IDL.Float64, Number.EPSILON, '4449444c000172000000000000b03c', 'eps'); - test_(IDL.Float64, Number.MIN_VALUE, '4449444c0001720100000000000000', 'min_value'); - test_(IDL.Float64, Number.MAX_VALUE, '4449444c000172ffffffffffffef7f', 'max_value'); - test_(IDL.Float64, Number.MIN_SAFE_INTEGER, '4449444c000172ffffffffffff3fc3', 'min_safe_integer'); - test_(IDL.Float64, Number.MAX_SAFE_INTEGER, '4449444c000172ffffffffffff3f43', 'max_safe_integer'); -}); - -test('IDL encoding (fixed-width number)', () => { - // Fixed-width number - test_(IDL.Int8, 0, '4449444c00017700', 'Int8'); - test_(IDL.Int8, -1, '4449444c000177ff', 'Int8'); - test_(IDL.Int8, 42, '4449444c0001772a', 'Int8'); - test_(IDL.Int8, 127, '4449444c0001777f', 'Int8'); - test_(IDL.Int8, -128, '4449444c00017780', 'Int8'); - test_(IDL.Int32, 42, '4449444c0001752a000000', 'Int32'); - test_(IDL.Int32, -42, '4449444c000175d6ffffff', 'Negative Int32'); - test_(IDL.Int32, 1234567890, '4449444c000175d2029649', 'Positive Int32'); - test_(IDL.Int32, -1234567890, '4449444c0001752efd69b6', 'Negative Int32'); - test_(IDL.Int32, -0x7fffffff, '4449444c00017501000080', 'Negative Int32'); - test_(IDL.Int32, 0x7fffffff, '4449444c000175ffffff7f', 'Positive Int32'); - test_(IDL.Int64, new BigNumber(42), '4449444c0001742a00000000000000', 'Int64'); - test_(IDL.Int64, new BigNumber(-42), '4449444c000174d6ffffffffffffff', 'Int64'); - test_(IDL.Int64, new BigNumber(1234567890), '4449444c000174d202964900000000', 'Positive Int64'); - test_(IDL.Nat8, 42, '4449444c00017b2a', 'Nat8'); - test_(IDL.Nat8, 0, '4449444c00017b00', 'Nat8'); - test_(IDL.Nat8, 255, '4449444c00017bff', 'Nat8'); - test_(IDL.Nat32, 0, '4449444c00017900000000', 'Nat32'); - test_(IDL.Nat32, 42, '4449444c0001792a000000', 'Nat32'); - test_(IDL.Nat32, 0xffffffff, '4449444c000179ffffffff', 'Nat32'); - test_(IDL.Nat64, new BigNumber(1234567890), '4449444c000178d202964900000000', 'Positive Nat64'); - expect(() => IDL.encode([IDL.Nat32], [-42])).toThrow(/Invalid nat32 argument/); - expect(() => IDL.encode([IDL.Int8], [256])).toThrow(/Invalid int8 argument/); - expect(() => IDL.encode([IDL.Int32], [0xffffffff])).toThrow(/Invalid int32 argument/); -}); - -test('IDL encoding (tuple)', () => { - // Tuple - test_( - IDL.Tuple(IDL.Int, IDL.Text), - [new BigNumber(42), '💩'], - '4449444c016c02007c017101002a04f09f92a9', - 'Pairs', - ); - expect(() => IDL.encode([IDL.Tuple(IDL.Int, IDL.Text)], [[0]])).toThrow( - /Invalid record {int; text} argument/, - ); -}); - -test('IDL encoding (array)', () => { - // Array - test_( - IDL.Vec(IDL.Int), - [0, 1, 2, 3].map(x => new BigNumber(x)), - '4449444c016d7c01000400010203', - 'Array of Ints', - ); - expect(() => IDL.encode([IDL.Vec(IDL.Int)], [new BigNumber(0)])).toThrow( - /Invalid vec int argument/, - ); - expect(() => IDL.encode([IDL.Vec(IDL.Int)], [['fail']])).toThrow(/Invalid vec int argument/); -}); - -test('IDL encoding (array + tuples)', () => { - // Array of Tuple - test_( - IDL.Vec(IDL.Tuple(IDL.Int, IDL.Text)), - [[new BigNumber(42), 'text']], - '4449444c026c02007c01716d000101012a0474657874', - 'Arr of Tuple', - ); - - // Nested Tuples - test_( - IDL.Tuple(IDL.Tuple(IDL.Tuple(IDL.Tuple(IDL.Null)))), - [[[[null]]]], - '4449444c046c01007f6c0100006c0100016c0100020103', - 'Nested Tuples', - ); -}); - -test('IDL encoding (record)', () => { - // Record - test_(IDL.Record({}), {}, '4449444c016c000100', 'Empty record'); - expect(() => IDL.encode([IDL.Record({ a: IDL.Text })], [{ b: 'b' }])).toThrow( - /Record is missing key/, - ); - - // Test that additional keys are ignored - testEncode( - IDL.Record({ foo: IDL.Text, bar: IDL.Int }), - { foo: '💩', bar: new BigNumber(42), baz: new BigNumber(0) }, - '4449444c016c02d3e3aa027c868eb7027101002a04f09f92a9', - 'Record', - ); - testEncode( - IDL.Record({ foo: IDL.Text, bar: IDL.Int }), - { foo: '💩', bar: 42 }, - '4449444c016c02d3e3aa027c868eb7027101002a04f09f92a9', - 'Record', - ); -}); - -test('IDL decoding (skip fields)', () => { - testDecode( - IDL.Record({ foo: IDL.Text, bar: IDL.Int }), - { foo: '💩', bar: new BigNumber(42) }, - '4449444c016c04017f027ed3e3aa027c868eb702710100012a04f09f92a9', - 'ignore record fields', - ); - testDecode( - IDL.Variant({ ok: IDL.Text, err: IDL.Text }), - { ok: 'good' }, - '4449444c016b03017e9cc20171e58eb4027101000104676f6f64', - 'adjust variant index', - ); - const recordType = IDL.Record({ foo: IDL.Int32, bar: IDL.Bool }); - const recordValue = { foo: 42, bar: true }; - test_( - IDL.Record({ foo: IDL.Int32, bar: recordType, baz: recordType, bib: recordType }), - { foo: 42, bar: recordValue, baz: recordValue, bib: recordValue }, - '4449444c026c02d3e3aa027e868eb702756c04d3e3aa0200dbe3aa0200bbf1aa0200868eb702750101012a000000012a000000012a0000002a000000', - 'nested record', - ); - testDecode( - IDL.Record({ baz: IDL.Record({ foo: IDL.Int32 }) }), - { baz: { foo: 42 } }, - '4449444c026c02d3e3aa027e868eb702756c04d3e3aa0200dbe3aa0200bbf1aa0200868eb702750101012a000000012a000000012a0000002a000000', - 'skip nested fields', - ); -}); - -test('IDL encoding (numbered record)', () => { - // Record - test_( - IDL.Record({ _0_: IDL.Int8, _1_: IDL.Bool }), - { _0_: 42, _1_: true }, - '4449444c016c020077017e01002a01', - 'Numbered record', - ); - // Test Tuple and numbered record are exact the same - test_(IDL.Tuple(IDL.Int8, IDL.Bool), [42, true], '4449444c016c020077017e01002a01', 'Tuple'); - test_( - IDL.Tuple(IDL.Tuple(IDL.Int8, IDL.Bool), IDL.Record({ _0_: IDL.Int8, _1_: IDL.Bool })), - [[42, true], { _0_: 42, _1_: true }], - '4449444c026c020077017e6c020000010001012a012a01', - 'Tuple and Record', - ); - test_( - IDL.Record({ _2_: IDL.Int8, 2: IDL.Bool }), - { _2_: 42, 2: true }, - '4449444c016c020277327e01002a01', - 'Mixed record', - ); -}); - -test('IDL encoding (bool)', () => { - // Bool - test_(IDL.Bool, true, '4449444c00017e01', 'true'); - test_(IDL.Bool, false, '4449444c00017e00', 'false'); - expect(() => IDL.encode([IDL.Bool], [0])).toThrow(/Invalid bool argument/); - expect(() => IDL.encode([IDL.Bool], ['false'])).toThrow(/Invalid bool argument/); -}); - -test('IDL encoding (principal)', () => { - // Principal - test_( - IDL.Principal, - Principal.fromText('w7x7r-cok77-xa'), - '4449444c0001680103caffee', - 'principal', - ); - test_( - IDL.Principal, - Principal.fromText('2chl6-4hpzw-vqaaa-aaaaa-c'), - '4449444c0001680109efcdab000000000001', - 'principal', - ); - expect(() => IDL.encode([IDL.Principal], ['w7x7r-cok77-xa'])).toThrow( - /Invalid principal argument/, - ); - expect(() => IDL.decode([IDL.Principal], Buffer.from('4449444c00016803caffee', 'hex'))).toThrow( - /Cannot decode principal/, - ); -}); - -test('IDL encoding (function)', () => { - // Function - test_( - IDL.Func([IDL.Text], [IDL.Nat], []), - [Principal.fromText('w7x7r-cok77-xa'), 'foo'], - '4449444c016a0171017d000100010103caffee03666f6f', - 'function', - ); - test_( - IDL.Func([IDL.Text], [IDL.Nat], ['query']), - [Principal.fromText('w7x7r-cok77-xa'), 'foo'], - '4449444c016a0171017d01010100010103caffee03666f6f', - 'query function', - ); -}); - -test('IDL encoding (service)', () => { - // Service - test_( - IDL.Service({ foo: IDL.Func([IDL.Text], [IDL.Nat], []) }), - Principal.fromText('w7x7r-cok77-xa'), - '4449444c026a0171017d00690103666f6f0001010103caffee', - 'service', - ); - test_( - IDL.Service({ foo: IDL.Func([IDL.Text], [IDL.Nat], ['query']) }), - Principal.fromText('w7x7r-cok77-xa'), - '4449444c026a0171017d0101690103666f6f0001010103caffee', - 'service', - ); - test_( - IDL.Service({ - foo: IDL.Func([IDL.Text], [IDL.Nat], []), - foo2: IDL.Func([IDL.Text], [IDL.Nat], []), - }), - Principal.fromText('w7x7r-cok77-xa'), - '4449444c026a0171017d00690203666f6f0004666f6f320001010103caffee', - 'service', - ); -}); - -test('IDL encoding (variants)', () => { - // Variants - const Result = IDL.Variant({ ok: IDL.Text, err: IDL.Text }); - test_(Result, { ok: 'good' }, '4449444c016b029cc20171e58eb4027101000004676f6f64', 'Result ok'); - test_(Result, { err: 'uhoh' }, '4449444c016b029cc20171e58eb402710100010475686f68', 'Result err'); - expect(() => IDL.encode([Result], [{}])).toThrow(/Invalid variant {ok:text; err:text} argument/); - expect(() => IDL.encode([Result], [{ ok: 'ok', err: 'err' }])).toThrow( - /Invalid variant {ok:text; err:text} argument/, - ); - - // Test that nullary constructors work as expected - test_( - IDL.Variant({ foo: IDL.Null }), - { foo: null }, - '4449444c016b01868eb7027f010000', - 'Nullary constructor in variant', - ); - - // Test that Empty within variants works as expected - test_( - IDL.Variant({ ok: IDL.Text, err: IDL.Empty }), - { ok: 'good' }, - '4449444c016b029cc20171e58eb4026f01000004676f6f64', - 'Empty within variants', - ); - expect(() => - IDL.encode([IDL.Variant({ ok: IDL.Text, err: IDL.Empty })], [{ err: 'uhoh' }]), - ).toThrow(/Invalid variant {ok:text; err:empty} argument:/); - - // Test for option - test_(IDL.Opt(IDL.Nat), [], '4449444c016e7d010000', 'None option'); - test_(IDL.Opt(IDL.Nat), [new BigNumber(1)], '4449444c016e7d01000101', 'Some option'); - test_( - IDL.Opt(IDL.Opt(IDL.Nat)), - [[new BigNumber(1)]], - '4449444c026e7d6e000101010101', - 'Nested option', - ); - test_(IDL.Opt(IDL.Opt(IDL.Null)), [[null]], '4449444c026e7f6e0001010101', 'Null option'); - - // Type description sharing - test_( - IDL.Tuple(IDL.Vec(IDL.Int), IDL.Vec(IDL.Nat), IDL.Vec(IDL.Int), IDL.Vec(IDL.Nat)), - [[], [], [], []], - '4449444c036d7c6d7d6c040000010102000301010200000000', - 'Type sharing', - ); -}); - -test('IDL encoding (rec)', () => { - // Test for recursive types - const List = IDL.Rec(); - expect(() => IDL.encode([List], [[]])).toThrow(/Recursive type uninitialized/); - List.fill(IDL.Opt(IDL.Record({ head: IDL.Int, tail: List }))); - test_(List, [], '4449444c026e016c02a0d2aca8047c90eddae70400010000', 'Empty list'); - test_( - List, - [{ head: new BigNumber(1), tail: [{ head: new BigNumber(2), tail: [] }] }], - '4449444c026e016c02a0d2aca8047c90eddae7040001000101010200', - 'List', - ); - - // Mutual recursion - const List1 = IDL.Rec(); - const List2 = IDL.Rec(); - List1.fill(IDL.Opt(List2)); - List2.fill(IDL.Record({ head: IDL.Int, tail: List1 })); - test_(List1, [], '4449444c026e016c02a0d2aca8047c90eddae70400010000', 'Empty list'); - test_( - List1, - [{ head: new BigNumber(1), tail: [{ head: new BigNumber(2), tail: [] }] }], - '4449444c026e016c02a0d2aca8047c90eddae7040001000101010200', - 'List', - ); -}); - -test('IDL encoding (multiple arguments)', () => { - const Result = IDL.Variant({ ok: IDL.Text, err: IDL.Text }); - - // Test for multiple arguments - test_args( - [IDL.Nat, IDL.Opt(IDL.Text), Result], - [new BigNumber(42), ['test'], { ok: 'good' }], - '4449444c026e716b029cc20171e58eb40271037d00012a0104746573740004676f6f64', - 'Multiple arguments', - ); - test_args([], [], '4449444c0000', 'empty args'); -}); diff --git a/src/agent/javascript/src/idl.ts b/src/agent/javascript/src/idl.ts deleted file mode 100644 index b66d9208df..0000000000 --- a/src/agent/javascript/src/idl.ts +++ /dev/null @@ -1,1619 +0,0 @@ -// tslint:disable:max-classes-per-file -import BigNumber from 'bignumber.js'; -import Pipe = require('buffer-pipe'); -import { Buffer } from 'buffer/'; -import { Principal as PrincipalId } from './principal'; -import { JsonValue } from './types'; -import { idlLabelToId } from './utils/hash'; -import { lebDecode, lebEncode, safeRead, slebDecode, slebEncode } from './utils/leb128'; -import { readIntLE, readUIntLE, writeIntLE, writeUIntLE } from './utils/leb128'; - -// tslint:disable:max-line-length -/** - * This module provides a combinator library to create serializers/deserializers - * between JavaScript values and IDL used by canisters on the Internet Computer, - * as documented at https://github.com/dfinity/candid/blob/119703ba342d2fef6ab4972d2541b9fe36ae8e36/spec/Candid.md - */ -// tslint:enable:max-line-length - -const enum IDLTypeIds { - Null = -1, - Bool = -2, - Nat = -3, - Int = -4, - Float32 = -13, - Float64 = -14, - Text = -15, - Reserved = -16, - Empty = -17, - Opt = -18, - Vector = -19, - Record = -20, - Variant = -21, - Func = -22, - Service = -23, - Principal = -24, -} - -const magicNumber = 'DIDL'; - -function zipWith(xs: TX[], ys: TY[], f: (a: TX, b: TY) => TR): TR[] { - return xs.map((x, i) => f(x, ys[i])); -} - -/** - * An IDL Type Table, which precedes the data in the stream. - */ -class TypeTable { - // List of types. Needs to be an array as the index needs to be stable. - private _typs: Buffer[] = []; - private _idx = new Map(); - - public has(obj: ConstructType) { - return this._idx.has(obj.name); - } - - public add(type: ConstructType, buf: Buffer) { - const idx = this._typs.length; - this._idx.set(type.name, idx); - this._typs.push(buf); - } - - public merge(obj: ConstructType, knot: string) { - const idx = this._idx.get(obj.name); - const knotIdx = this._idx.get(knot); - if (idx === undefined) { - throw new Error('Missing type index for ' + obj); - } - if (knotIdx === undefined) { - throw new Error('Missing type index for ' + knot); - } - this._typs[idx] = this._typs[knotIdx]; - - // Delete the type. - this._typs.splice(knotIdx, 1); - this._idx.delete(knot); - } - - public encode() { - const len = lebEncode(this._typs.length); - const buf = Buffer.concat(this._typs); - return Buffer.concat([len, buf]); - } - - public indexOf(typeName: string) { - if (!this._idx.has(typeName)) { - throw new Error('Missing type index for ' + typeName); - } - return slebEncode(this._idx.get(typeName) || 0); - } -} - -export abstract class Visitor { - public visitType(t: Type, data: D): R { - throw new Error('Not implemented'); - } - public visitPrimitive(t: PrimitiveType, data: D): R { - return this.visitType(t, data); - } - public visitEmpty(t: EmptyClass, data: D): R { - return this.visitPrimitive(t, data); - } - public visitBool(t: BoolClass, data: D): R { - return this.visitPrimitive(t, data); - } - public visitNull(t: NullClass, data: D): R { - return this.visitPrimitive(t, data); - } - public visitReserved(t: ReservedClass, data: D): R { - return this.visitPrimitive(t, data); - } - public visitText(t: TextClass, data: D): R { - return this.visitPrimitive(t, data); - } - public visitNumber(t: PrimitiveType, data: D): R { - return this.visitPrimitive(t, data); - } - public visitInt(t: IntClass, data: D): R { - return this.visitNumber(t, data); - } - public visitNat(t: NatClass, data: D): R { - return this.visitNumber(t, data); - } - public visitFloat(t: FloatClass, data: D): R { - return this.visitPrimitive(t, data); - } - public visitFixedInt(t: FixedIntClass, data: D): R { - return this.visitNumber(t, data); - } - public visitFixedNat(t: FixedNatClass, data: D): R { - return this.visitNumber(t, data); - } - public visitPrincipal(t: PrincipalClass, data: D): R { - return this.visitPrimitive(t, data); - } - - public visitConstruct(t: ConstructType, data: D): R { - return this.visitType(t, data); - } - public visitVec(t: VecClass, ty: Type, data: D): R { - return this.visitConstruct(t, data); - } - public visitOpt(t: OptClass, ty: Type, data: D): R { - return this.visitConstruct(t, data); - } - public visitRecord(t: RecordClass, fields: Array<[string, Type]>, data: D): R { - return this.visitConstruct(t, data); - } - public visitTuple(t: TupleClass, components: Type[], data: D): R { - const fields: Array<[string, Type]> = components.map((ty, i) => [`_${i}_`, ty]); - return this.visitRecord(t, fields, data); - } - public visitVariant(t: VariantClass, fields: Array<[string, Type]>, data: D): R { - return this.visitConstruct(t, data); - } - public visitRec(t: RecClass, ty: ConstructType, data: D): R { - return this.visitConstruct(ty, data); - } - public visitFunc(t: FuncClass, data: D): R { - return this.visitConstruct(t, data); - } - public visitService(t: ServiceClass, data: D): R { - return this.visitConstruct(t, data); - } -} - -/** - * Represents an IDL type. - */ -export abstract class Type { - public abstract readonly name: string; - public abstract accept(v: Visitor, d: D): R; - - /* Display type name */ - public display(): string { - return this.name; - } - - public valueToString(x: T): string { - return JSON.stringify(x); - } - - /* Implement `T` in the IDL spec, only needed for non-primitive types */ - public buildTypeTable(typeTable: TypeTable): void { - if (!typeTable.has(this)) { - this._buildTypeTableImpl(typeTable); - } - } - - /** - * Assert that JavaScript's `x` is the proper type represented by this - * Type. - */ - public abstract covariant(x: any): x is T; - - /** - * Encode the value. This needs to be public because it is used by - * encodeValue() from different types. - * @internal - */ - public abstract encodeValue(x: T): Buffer; - - /** - * Implement `I` in the IDL spec. - * Encode this type for the type table. - */ - public abstract encodeType(typeTable: TypeTable): Buffer; - - public abstract checkType(t: Type): Type; - public abstract decodeValue(x: Pipe, t: Type): T; - - protected abstract _buildTypeTableImpl(typeTable: TypeTable): void; -} - -export abstract class PrimitiveType extends Type { - public checkType(t: Type): Type { - if (this.name !== t.name) { - throw new Error(`type mismatch: type on the wire ${t.name}, expect type ${this.name}`); - } - return t; - } - public _buildTypeTableImpl(typeTable: TypeTable): void { - // No type table encoding for Primitive types. - return; - } -} - -export abstract class ConstructType extends Type { - public checkType(t: Type): ConstructType { - if (t instanceof RecClass) { - const ty = t.getType(); - if (typeof ty === 'undefined') { - throw new Error('type mismatch with uninitialized type'); - } - return ty; - } - throw new Error(`type mismatch: type on the wire ${t.name}, expect type ${this.name}`); - } - public encodeType(typeTable: TypeTable) { - return typeTable.indexOf(this.name); - } -} - -/** - * Represents an IDL Empty, a type which has no inhabitants. - * Since no values exist for this type, it cannot be serialised or deserialised. - * Result types like `Result` should always succeed. - */ -export class EmptyClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitEmpty(this, d); - } - - public covariant(x: any): x is never { - return false; - } - - public encodeValue(): never { - throw new Error('Empty cannot appear as a function argument'); - } - - public valueToString(): never { - throw new Error('Empty cannot appear as a value'); - } - - public encodeType() { - return slebEncode(IDLTypeIds.Empty); - } - - public decodeValue(): never { - throw new Error('Empty cannot appear as an output'); - } - - get name() { - return 'empty'; - } -} - -/** - * Represents an IDL Bool - */ -export class BoolClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitBool(this, d); - } - - public covariant(x: any): x is boolean { - return typeof x === 'boolean'; - } - - public encodeValue(x: boolean): Buffer { - const buf = Buffer.alloc(1); - buf.writeInt8(x ? 1 : 0, 0); - return buf; - } - - public encodeType() { - return slebEncode(IDLTypeIds.Bool); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - const x = safeRead(b, 1).toString('hex'); - if (x === '00') { - return false; - } else if (x === '01') { - return true; - } else { - throw new Error('Boolean value out of range'); - } - } - - get name() { - return 'bool'; - } -} - -/** - * Represents an IDL Null - */ -export class NullClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitNull(this, d); - } - - public covariant(x: any): x is null { - return x === null; - } - - public encodeValue() { - return Buffer.alloc(0); - } - - public encodeType() { - return slebEncode(IDLTypeIds.Null); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - return null; - } - - get name() { - return 'null'; - } -} - -/** - * Represents an IDL Reserved - */ -export class ReservedClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitReserved(this, d); - } - - public covariant(x: any): x is any { - return true; - } - - public encodeValue() { - return Buffer.alloc(0); - } - - public encodeType() { - return slebEncode(IDLTypeIds.Reserved); - } - - public decodeValue(b: Pipe, t: Type) { - if (t.name !== this.name) { - t.decodeValue(b, t); - } - return null; - } - - get name() { - return 'reserved'; - } -} - -function isValidUTF8(buf: Buffer): boolean { - return Buffer.compare(new Buffer(buf.toString(), 'utf8'), buf) === 0; -} - -/** - * Represents an IDL Text - */ -export class TextClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitText(this, d); - } - - public covariant(x: any): x is string { - return typeof x === 'string'; - } - - public encodeValue(x: string) { - const buf = Buffer.from(x, 'utf8'); - const len = lebEncode(buf.length); - return Buffer.concat([len, buf]); - } - - public encodeType() { - return slebEncode(IDLTypeIds.Text); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - const len = lebDecode(b).toNumber(); - const buf = safeRead(b, len); - if (!isValidUTF8(buf)) { - throw new Error('Not valid UTF8 text'); - } - return buf.toString('utf8'); - } - - get name() { - return 'text'; - } - - public valueToString(x: string) { - return '"' + x + '"'; - } -} - -/** - * Represents an IDL Int - */ -export class IntClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitInt(this, d); - } - - public covariant(x: any): x is BigNumber { - // We allow encoding of JavaScript plain numbers. - // But we will always decode to BigNumber. - return (BigNumber.isBigNumber(x) && x.isInteger()) || Number.isInteger(x); - } - - public encodeValue(x: BigNumber | number) { - return slebEncode(x); - } - - public encodeType() { - return slebEncode(IDLTypeIds.Int); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - return slebDecode(b); - } - - get name() { - return 'int'; - } - - public valueToString(x: BigNumber) { - return x.toFixed(); - } -} - -/** - * Represents an IDL Nat - */ -export class NatClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitNat(this, d); - } - - public covariant(x: any): x is BigNumber { - // We allow encoding of JavaScript plain numbers. - // But we will always decode to BigNumber. - return ( - (BigNumber.isBigNumber(x) && x.isInteger() && !x.isNegative()) || - (Number.isInteger(x) && x >= 0) - ); - } - - public encodeValue(x: BigNumber | number) { - return lebEncode(x); - } - - public encodeType() { - return slebEncode(IDLTypeIds.Nat); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - return lebDecode(b); - } - - get name() { - return 'nat'; - } - - public valueToString(x: BigNumber) { - return x.toFixed(); - } -} - -/** - * Represents an IDL Float - */ -export class FloatClass extends PrimitiveType { - constructor(private _bits: number) { - super(); - if (_bits !== 32 && _bits !== 64) { - throw new Error('not a valid float type'); - } - } - public accept(v: Visitor, d: D): R { - return v.visitFloat(this, d); - } - - public covariant(x: any): x is number { - return typeof x === 'number' || x instanceof Number; - } - - public encodeValue(x: number) { - const buf = Buffer.allocUnsafe(this._bits / 8); - if (this._bits === 32) { - buf.writeFloatLE(x, 0); - } else { - buf.writeDoubleLE(x, 0); - } - return buf; - } - - public encodeType() { - const opcode = this._bits === 32 ? IDLTypeIds.Float32 : IDLTypeIds.Float64; - return slebEncode(opcode); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - const x = safeRead(b, this._bits / 8); - if (this._bits === 32) { - return x.readFloatLE(0); - } else { - return x.readDoubleLE(0); - } - } - - get name() { - return 'float' + this._bits; - } - - public valueToString(x: number) { - return x.toString(); - } -} - -/** - * Represents an IDL fixed-width Int(n) - */ -export class FixedIntClass extends PrimitiveType { - constructor(private _bits: number) { - super(); - } - - public accept(v: Visitor, d: D): R { - return v.visitFixedInt(this, d); - } - - public covariant(x: any): x is BigNumber { - const min = new BigNumber(2).pow(this._bits - 1).negated(); - const max = new BigNumber(2).pow(this._bits - 1).minus(1); - if (BigNumber.isBigNumber(x) && x.isInteger()) { - return x.gte(min) && x.lte(max); - } else if (Number.isInteger(x)) { - const v = new BigNumber(x); - return v.gte(min) && v.lte(max); - } else { - return false; - } - } - - public encodeValue(x: BigNumber | number) { - return writeIntLE(x, this._bits / 8); - } - - public encodeType() { - const offset = Math.log2(this._bits) - 3; - return slebEncode(-9 - offset); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - const num = readIntLE(b, this._bits / 8); - if (this._bits <= 32) { - return num.toNumber(); - } else { - return num; - } - } - - get name() { - return `int${this._bits}`; - } - - public valueToString(x: BigNumber | number) { - return x.toString(); - } -} - -/** - * Represents an IDL fixed-width Nat(n) - */ -export class FixedNatClass extends PrimitiveType { - constructor(private _bits: number) { - super(); - } - - public accept(v: Visitor, d: D): R { - return v.visitFixedNat(this, d); - } - - public covariant(x: any): x is BigNumber { - const max = new BigNumber(2).pow(this._bits); - if (BigNumber.isBigNumber(x) && x.isInteger() && !x.isNegative()) { - return x.lt(max); - } else if (Number.isInteger(x) && x >= 0) { - const v = new BigNumber(x); - return v.lt(max); - } else { - return false; - } - } - - public encodeValue(x: BigNumber | number) { - return writeUIntLE(x, this._bits / 8); - } - - public encodeType() { - const offset = Math.log2(this._bits) - 3; - return slebEncode(-5 - offset); - } - - public decodeValue(b: Pipe, t: Type) { - this.checkType(t); - const num = readUIntLE(b, this._bits / 8); - if (this._bits <= 32) { - return num.toNumber(); - } else { - return num; - } - } - - get name() { - return `nat${this._bits}`; - } - - public valueToString(x: BigNumber | number) { - return x.toString(); - } -} - -/** - * Represents an IDL Array - * @param {Type} t - */ -export class VecClass extends ConstructType { - constructor(protected _type: Type) { - super(); - } - - public accept(v: Visitor, d: D): R { - return v.visitVec(this, this._type, d); - } - - public covariant(x: any): x is T[] { - return Array.isArray(x) && x.every(v => this._type.covariant(v)); - } - - public encodeValue(x: T[]) { - const len = lebEncode(x.length); - return Buffer.concat([len, ...x.map(d => this._type.encodeValue(d))]); - } - - public _buildTypeTableImpl(typeTable: TypeTable) { - this._type.buildTypeTable(typeTable); - - const opCode = slebEncode(IDLTypeIds.Vector); - const buffer = this._type.encodeType(typeTable); - typeTable.add(this, Buffer.concat([opCode, buffer])); - } - - public decodeValue(b: Pipe, t: Type): any[] { - const vec = this.checkType(t); - if (!(vec instanceof VecClass)) { - throw new Error('Not a vector type'); - } - const len = lebDecode(b).toNumber(); - const rets: any[] = []; - for (let i = 0; i < len; i++) { - rets.push(this._type.decodeValue(b, vec._type)); - } - return rets; - } - - get name() { - return `vec ${this._type.name}`; - } - - public display() { - return `vec ${this._type.display()}`; - } - - public valueToString(x: T[]) { - const elements = x.map(e => this._type.valueToString(e)); - return 'vec {' + elements.join('; ') + '}'; - } -} - -/** - * Represents an IDL Option - * @param {Type} t - */ -export class OptClass extends ConstructType<[T] | []> { - constructor(protected _type: Type) { - super(); - } - - public accept(v: Visitor, d: D): R { - return v.visitOpt(this, this._type, d); - } - - public covariant(x: any): x is [T] | [] { - return Array.isArray(x) && (x.length === 0 || (x.length === 1 && this._type.covariant(x[0]))); - } - - public encodeValue(x: [T] | []) { - if (x.length === 0) { - return Buffer.from([0]); - } else { - return Buffer.concat([Buffer.from([1]), this._type.encodeValue(x[0])]); - } - } - - public _buildTypeTableImpl(typeTable: TypeTable) { - this._type.buildTypeTable(typeTable); - - const opCode = slebEncode(IDLTypeIds.Opt); - const buffer = this._type.encodeType(typeTable); - typeTable.add(this, Buffer.concat([opCode, buffer])); - } - - public decodeValue(b: Pipe, t: Type): [T] | [] { - const opt = this.checkType(t); - if (!(opt instanceof OptClass)) { - throw new Error('Not an option type'); - } - const len = safeRead(b, 1).toString('hex'); - if (len === '00') { - return []; - } else if (len === '01') { - return [this._type.decodeValue(b, opt._type)]; - } else { - throw new Error('Not an option value'); - } - } - - get name() { - return `opt ${this._type.name}`; - } - - public display() { - return `opt ${this._type.display()}`; - } - - public valueToString(x: [T] | []) { - if (x.length === 0) { - return 'null'; - } else { - return `opt ${this._type.valueToString(x[0])}`; - } - } -} - -/** - * Represents an IDL Record - * @param {Object} [fields] - mapping of function name to Type - */ -export class RecordClass extends ConstructType> { - protected readonly _fields: Array<[string, Type]>; - - constructor(fields: Record = {}) { - super(); - this._fields = Object.entries(fields).sort((a, b) => idlLabelToId(a[0]) - idlLabelToId(b[0])); - } - - public accept(v: Visitor, d: D): R { - return v.visitRecord(this, this._fields, d); - } - - public tryAsTuple(): Type[] | null { - const res: Type[] = []; - for (let i = 0; i < this._fields.length; i++) { - const [key, type] = this._fields[i]; - if (key !== `_${i}_`) { - return null; - } - res.push(type); - } - return res; - } - - public covariant(x: any): x is Record { - return ( - typeof x === 'object' && - this._fields.every(([k, t]) => { - if (!x.hasOwnProperty(k)) { - throw new Error(`Record is missing key "${k}".`); - } - return t.covariant(x[k]); - }) - ); - } - - public encodeValue(x: Record) { - const values = this._fields.map(([key]) => x[key]); - const bufs = zipWith(this._fields, values, ([, c], d) => c.encodeValue(d)); - return Buffer.concat(bufs); - } - - public _buildTypeTableImpl(T: TypeTable) { - this._fields.forEach(([_, value]) => value.buildTypeTable(T)); - const opCode = slebEncode(IDLTypeIds.Record); - const len = lebEncode(this._fields.length); - const fields = this._fields.map(([key, value]) => - Buffer.concat([lebEncode(idlLabelToId(key)), value.encodeType(T)]), - ); - - T.add(this, Buffer.concat([opCode, len, Buffer.concat(fields)])); - } - - public decodeValue(b: Pipe, t: Type) { - const record = this.checkType(t); - if (!(record instanceof RecordClass)) { - throw new Error('Not a record type'); - } - const x: Record = {}; - let idx = 0; - for (const [hash, type] of record._fields) { - if (idx >= this._fields.length || idlLabelToId(this._fields[idx][0]) !== idlLabelToId(hash)) { - // skip field - type.decodeValue(b, type); - continue; - } - const [expectKey, expectType] = this._fields[idx]; - x[expectKey] = expectType.decodeValue(b, type); - idx++; - } - if (idx < this._fields.length) { - throw new Error('Cannot find field ' + this._fields[idx][0]); - } - return x; - } - - get name() { - const fields = this._fields.map(([key, value]) => key + ':' + value.name); - return `record {${fields.join('; ')}}`; - } - - public display() { - const fields = this._fields.map(([key, value]) => key + ':' + value.display()); - return `record {${fields.join('; ')}}`; - } - - public valueToString(x: Record) { - const values = this._fields.map(([key]) => x[key]); - const fields = zipWith(this._fields, values, ([k, c], d) => k + '=' + c.valueToString(d)); - return `record {${fields.join('; ')}}`; - } -} - -/** - * Represents Tuple, a syntactic sugar for Record. - * @param {Type} components - */ -export class TupleClass extends RecordClass { - protected readonly _components: Type[]; - - constructor(_components: Type[]) { - const x: Record = {}; - _components.forEach((e, i) => (x['_' + i + '_'] = e)); - super(x); - this._components = _components; - } - - public accept(v: Visitor, d: D): R { - return v.visitTuple(this, this._components, d); - } - - public covariant(x: any): x is T { - // `>=` because tuples can be covariant when encoded. - return ( - Array.isArray(x) && - x.length >= this._fields.length && - this._components.every((t, i) => t.covariant(x[i])) - ); - } - - public encodeValue(x: any[]) { - const bufs = zipWith(this._components, x, (c, d) => c.encodeValue(d)); - return Buffer.concat(bufs); - } - - public decodeValue(b: Pipe, t: Type): T { - const tuple = this.checkType(t); - if (!(tuple instanceof TupleClass)) { - throw new Error('not a tuple type'); - } - if (tuple._components.length < this._components.length) { - throw new Error('tuple mismatch'); - } - const res = []; - for (const [i, wireType] of tuple._components.entries()) { - if (i >= this._components.length) { - // skip value - wireType.decodeValue(b, wireType); - } else { - res.push(this._components[i].decodeValue(b, wireType)); - } - } - return res as T; - } - - public display() { - const fields = this._components.map(value => value.display()); - return `record {${fields.join('; ')}}`; - } - - public valueToString(values: any[]) { - const fields = zipWith(this._components, values, (c, d) => c.valueToString(d)); - return `record {${fields.join('; ')}}`; - } -} - -/** - * Represents an IDL Variant - * @param {Object} [fields] - mapping of function name to Type - */ -export class VariantClass extends ConstructType> { - private readonly _fields: Array<[string, Type]>; - - constructor(fields: Record = {}) { - super(); - this._fields = Object.entries(fields).sort((a, b) => idlLabelToId(a[0]) - idlLabelToId(b[0])); - } - - public accept(v: Visitor, d: D): R { - return v.visitVariant(this, this._fields, d); - } - - public covariant(x: any): x is Record { - return ( - typeof x === 'object' && - Object.entries(x).length === 1 && - this._fields.every(([k, v]) => { - return !x.hasOwnProperty(k) || v.covariant(x[k]); - }) - ); - } - - public encodeValue(x: Record) { - for (let i = 0; i < this._fields.length; i++) { - const [name, type] = this._fields[i]; - if (x.hasOwnProperty(name)) { - const idx = lebEncode(i); - const buf = type.encodeValue(x[name]); - - return Buffer.concat([idx, buf]); - } - } - throw Error('Variant has no data: ' + x); - } - - public _buildTypeTableImpl(typeTable: TypeTable) { - this._fields.forEach(([, type]) => { - type.buildTypeTable(typeTable); - }); - const opCode = slebEncode(IDLTypeIds.Variant); - const len = lebEncode(this._fields.length); - const fields = this._fields.map(([key, value]) => - Buffer.concat([lebEncode(idlLabelToId(key)), value.encodeType(typeTable)]), - ); - typeTable.add(this, Buffer.concat([opCode, len, ...fields])); - } - - public decodeValue(b: Pipe, t: Type) { - const variant = this.checkType(t); - if (!(variant instanceof VariantClass)) { - throw new Error('Not a variant type'); - } - const idx = lebDecode(b).toNumber(); - if (idx >= variant._fields.length) { - throw Error('Invalid variant index: ' + idx); - } - const [wireHash, wireType] = variant._fields[idx]; - for (const [key, expectType] of this._fields) { - if (idlLabelToId(wireHash) === idlLabelToId(key)) { - const value = expectType.decodeValue(b, wireType); - return { [key]: value }; - } - } - throw new Error('Cannot find field hash ' + wireHash); - } - - get name() { - const fields = this._fields.map(([key, type]) => key + ':' + type.name); - return `variant {${fields.join('; ')}}`; - } - - public display() { - const fields = this._fields.map( - ([key, type]) => key + (type.name === 'null' ? '' : `:${type.display()}`), - ); - return `variant {${fields.join('; ')}}`; - } - - public valueToString(x: Record) { - for (const [name, type] of this._fields) { - if (x.hasOwnProperty(name)) { - const value = type.valueToString(x[name]); - if (value === 'null') { - return `variant {${name}}`; - } else { - return `variant {${name}=${value}}`; - } - } - } - throw new Error('Variant has no data: ' + x); - } -} - -/** - * Represents a reference to an IDL type, used for defining recursive data - * types. - */ -export class RecClass extends ConstructType { - private static _counter = 0; - private _id = RecClass._counter++; - private _type: ConstructType | undefined = undefined; - - public accept(v: Visitor, d: D): R { - if (!this._type) { - throw Error('Recursive type uninitialized.'); - } - return v.visitRec(this, this._type, d); - } - - public fill(t: ConstructType) { - this._type = t; - } - - public getType() { - return this._type; - } - - public covariant(x: any): x is T { - return this._type ? this._type.covariant(x) : false; - } - - public encodeValue(x: T) { - if (!this._type) { - throw Error('Recursive type uninitialized.'); - } - return this._type.encodeValue(x); - } - - public _buildTypeTableImpl(typeTable: TypeTable) { - if (!this._type) { - throw Error('Recursive type uninitialized.'); - } - typeTable.add(this, Buffer.alloc(0)); - this._type.buildTypeTable(typeTable); - typeTable.merge(this, this._type.name); - } - - public decodeValue(b: Pipe, t: Type) { - if (!this._type) { - throw Error('Recursive type uninitialized.'); - } - return this._type.decodeValue(b, t); - } - - get name() { - return `rec_${this._id}`; - } - - public display() { - if (!this._type) { - throw Error('Recursive type uninitialized.'); - } - return `μ${this.name}.${this._type.name}`; - } - - public valueToString(x: T) { - if (!this._type) { - throw Error('Recursive type uninitialized.'); - } - return this._type.valueToString(x); - } -} - -function decodePrincipalId(b: Pipe): PrincipalId { - const x = safeRead(b, 1).toString('hex'); - if (x !== '01') { - throw new Error('Cannot decode principal'); - } - const len = lebDecode(b).toNumber(); - const hex = safeRead(b, len).toString('hex').toUpperCase(); - return PrincipalId.fromHex(hex); -} - -/** - * Represents an IDL principal reference - */ -export class PrincipalClass extends PrimitiveType { - public accept(v: Visitor, d: D): R { - return v.visitPrincipal(this, d); - } - - public covariant(x: any): x is PrincipalId { - return x && x._isPrincipal; - } - - public encodeValue(x: PrincipalId): Buffer { - const hex = x.toHex(); - const buf = Buffer.from(hex, 'hex'); - const len = lebEncode(buf.length); - return Buffer.concat([Buffer.from([1]), len, buf]); - } - - public encodeType() { - return slebEncode(IDLTypeIds.Principal); - } - - public decodeValue(b: Pipe, t: Type): PrincipalId { - this.checkType(t); - return decodePrincipalId(b); - } - - get name() { - return 'principal'; - } - public valueToString(x: PrincipalId) { - return `${this.name} "${x.toText()}"`; - } -} - -/** - * Represents an IDL function reference. - * @param argTypes Argument types. - * @param retTypes Return types. - * @param annotations Function annotations. - */ -export class FuncClass extends ConstructType<[PrincipalId, string]> { - public static argsToString(types: Type[], v: any[]) { - if (types.length !== v.length) { - throw new Error('arity mismatch'); - } - return '(' + types.map((t, i) => t.valueToString(v[i])).join(', ') + ')'; - } - - constructor(public argTypes: Type[], public retTypes: Type[], public annotations: string[] = []) { - super(); - } - - public accept(v: Visitor, d: D): R { - return v.visitFunc(this, d); - } - public covariant(x: any): x is [PrincipalId, string] { - return ( - Array.isArray(x) && x.length === 2 && x[0] && x[0]._isPrincipal && typeof x[1] === 'string' - ); - } - - public encodeValue(x: [PrincipalId, string]): Buffer { - const hex = x[0].toHex(); - const buf = Buffer.from(hex, 'hex'); - const len = lebEncode(buf.length); - const canister = Buffer.concat([Buffer.from([1]), len, buf]); - - const method = Buffer.from(x[1], 'utf8'); - const methodLen = lebEncode(method.length); - return Buffer.concat([Buffer.from([1]), canister, methodLen, method]); - } - - public _buildTypeTableImpl(T: TypeTable) { - this.argTypes.forEach(arg => arg.buildTypeTable(T)); - this.retTypes.forEach(arg => arg.buildTypeTable(T)); - - const opCode = slebEncode(IDLTypeIds.Func); - const argLen = lebEncode(this.argTypes.length); - const args = Buffer.concat(this.argTypes.map(arg => arg.encodeType(T))); - const retLen = lebEncode(this.retTypes.length); - const rets = Buffer.concat(this.retTypes.map(arg => arg.encodeType(T))); - const annLen = lebEncode(this.annotations.length); - const anns = Buffer.concat(this.annotations.map(a => this.encodeAnnotation(a))); - - T.add(this, Buffer.concat([opCode, argLen, args, retLen, rets, annLen, anns])); - } - - public decodeValue(b: Pipe): [PrincipalId, string] { - const x = safeRead(b, 1).toString('hex'); - if (x !== '01') { - throw new Error('Cannot decode function reference'); - } - const canister = decodePrincipalId(b); - - const mLen = lebDecode(b).toNumber(); - const buf = safeRead(b, mLen); - if (!isValidUTF8(buf)) { - throw new Error('Not valid UTF8 method name'); - } - const method = buf.toString('utf8'); - return [canister, method]; - } - - get name() { - const args = this.argTypes.map(arg => arg.name).join(', '); - const rets = this.retTypes.map(arg => arg.name).join(', '); - const annon = ' ' + this.annotations.join(' '); - return `(${args}) -> (${rets})${annon}`; - } - - public valueToString([principal, str]: [PrincipalId, string]) { - return `func "${principal.toText()}".${str}`; - } - - public display(): string { - const args = this.argTypes.map(arg => arg.display()).join(', '); - const rets = this.retTypes.map(arg => arg.display()).join(', '); - const annon = ' ' + this.annotations.join(' '); - return `(${args}) → (${rets})${annon}`; - } - - private encodeAnnotation(ann: string): Buffer { - if (ann === 'query') { - return Buffer.from([1]); - } else if (ann === 'oneway') { - return Buffer.from([2]); - } else { - throw new Error('Illeagal function annotation'); - } - } -} - -export class ServiceClass extends ConstructType { - public readonly _fields: Array<[string, FuncClass]>; - constructor(fields: Record) { - super(); - this._fields = Object.entries(fields).sort((a, b) => idlLabelToId(a[0]) - idlLabelToId(b[0])); - } - public accept(v: Visitor, d: D): R { - return v.visitService(this, d); - } - public covariant(x: any): x is PrincipalId { - return x && x._isPrincipal; - } - - public encodeValue(x: PrincipalId): Buffer { - const hex = x.toHex(); - const buf = Buffer.from(hex, 'hex'); - const len = lebEncode(buf.length); - return Buffer.concat([Buffer.from([1]), len, buf]); - } - - public _buildTypeTableImpl(T: TypeTable) { - this._fields.forEach(([_, func]) => func.buildTypeTable(T)); - const opCode = slebEncode(IDLTypeIds.Service); - const len = lebEncode(this._fields.length); - const meths = this._fields.map(([label, func]) => { - const labelBuf = Buffer.from(label, 'utf8'); - const labelLen = lebEncode(labelBuf.length); - return Buffer.concat([labelLen, labelBuf, func.encodeType(T)]); - }); - - T.add(this, Buffer.concat([opCode, len, Buffer.concat(meths)])); - } - - public decodeValue(b: Pipe): PrincipalId { - return decodePrincipalId(b); - } - get name() { - const fields = this._fields.map(([key, value]) => key + ':' + value.name); - return `service {${fields.join('; ')}}`; - } - - public valueToString(x: PrincipalId) { - return `service "${x.toText()}"`; - } -} - -/** - * Encode a array of values - * @returns {Buffer} serialised value - */ -export function encode(argTypes: Array>, args: any[]) { - if (args.length < argTypes.length) { - throw Error('Wrong number of message arguments'); - } - - const typeTable = new TypeTable(); - argTypes.forEach(t => t.buildTypeTable(typeTable)); - - const magic = Buffer.from(magicNumber, 'utf8'); - const table = typeTable.encode(); - const len = lebEncode(args.length); - const typs = Buffer.concat(argTypes.map(t => t.encodeType(typeTable))); - const vals = Buffer.concat( - zipWith(argTypes, args, (t, x) => { - if (!t.covariant(x)) { - throw new Error(`Invalid ${t.display()} argument: "${JSON.stringify(x)}"`); - } - - return t.encodeValue(x); - }), - ); - - return Buffer.concat([magic, table, len, typs, vals]); -} - -/** - * Decode a binary value - * @param retTypes - Types expected in the buffer. - * @param bytes - hex-encoded string, or buffer. - * @returns Value deserialised to JS type - */ -export function decode(retTypes: Type[], bytes: Buffer): JsonValue[] { - const b = new Pipe(bytes); - - if (bytes.byteLength < magicNumber.length) { - throw new Error('Message length smaller than magic number'); - } - const magic = safeRead(b, magicNumber.length).toString(); - if (magic !== magicNumber) { - throw new Error('Wrong magic number: ' + magic); - } - - function readTypeTable(pipe: Pipe): [Array<[IDLTypeIds, any]>, number[]] { - const typeTable: Array<[IDLTypeIds, any]> = []; - const len = lebDecode(pipe).toNumber(); - - for (let i = 0; i < len; i++) { - const ty = slebDecode(pipe).toNumber(); - switch (ty) { - case IDLTypeIds.Opt: - case IDLTypeIds.Vector: { - const t = slebDecode(pipe).toNumber(); - typeTable.push([ty, t]); - break; - } - case IDLTypeIds.Record: - case IDLTypeIds.Variant: { - const fields = []; - let objectLength = lebDecode(pipe).toNumber(); - let prevHash; - while (objectLength--) { - const hash = lebDecode(pipe).toNumber(); - if (hash >= Math.pow(2, 32)) { - throw new Error('field id out of 32-bit range'); - } - if (typeof prevHash === 'number' && prevHash >= hash) { - throw new Error('field id collision or not sorted'); - } - prevHash = hash; - const t = slebDecode(pipe).toNumber(); - fields.push([hash, t]); - } - typeTable.push([ty, fields]); - break; - } - case IDLTypeIds.Func: { - for (let k = 0; k < 2; k++) { - let funcLength = lebDecode(pipe).toNumber(); - while (funcLength--) { - slebDecode(pipe); - } - } - const annLen = lebDecode(pipe).toNumber(); - safeRead(pipe, annLen); - typeTable.push([ty, undefined]); - break; - } - case IDLTypeIds.Service: { - let servLength = lebDecode(pipe).toNumber(); - while (servLength--) { - const l = lebDecode(pipe).toNumber(); - safeRead(pipe, l); - slebDecode(pipe); - } - typeTable.push([ty, undefined]); - break; - } - default: - throw new Error('Illegal op_code: ' + ty); - } - } - - const rawList: number[] = []; - const length = lebDecode(pipe).toNumber(); - for (let i = 0; i < length; i++) { - rawList.push(slebDecode(pipe).toNumber()); - } - return [typeTable, rawList]; - } - const [rawTable, rawTypes] = readTypeTable(b); - if (rawTypes.length < retTypes.length) { - throw new Error('Wrong number of return values'); - } - - const table: RecClass[] = rawTable.map(_ => Rec()); - function getType(t: number): Type { - if (t < -24) { - throw new Error('future value not supported'); - } - if (t < 0) { - switch (t) { - case -1: - return Null; - case -2: - return Bool; - case -3: - return Nat; - case -4: - return Int; - case -5: - return Nat8; - case -6: - return Nat16; - case -7: - return Nat32; - case -8: - return Nat64; - case -9: - return Int8; - case -10: - return Int16; - case -11: - return Int32; - case -12: - return Int64; - case -13: - return Float32; - case -14: - return Float64; - case -15: - return Text; - case -16: - return Reserved; - case -17: - return Empty; - case -24: - return Principal; - default: - throw new Error('Illegal op_code: ' + t); - } - } - if (t >= rawTable.length) { - throw new Error('type index out of range'); - } - return table[t]; - } - function buildType(entry: [IDLTypeIds, any]): Type { - switch (entry[0]) { - case IDLTypeIds.Vector: { - const ty = getType(entry[1]); - return Vec(ty); - } - case IDLTypeIds.Opt: { - const ty = getType(entry[1]); - return Opt(ty); - } - case IDLTypeIds.Record: { - const fields: Record = {}; - for (const [hash, ty] of entry[1]) { - const name = `_${hash}_`; - fields[name] = getType(ty); - } - const record = Record(fields); - const tuple = record.tryAsTuple(); - if (Array.isArray(tuple)) { - return Tuple(...tuple); - } else { - return record; - } - } - case IDLTypeIds.Variant: { - const fields: Record = {}; - for (const [hash, ty] of entry[1]) { - const name = `_${hash}_`; - fields[name] = getType(ty); - } - return Variant(fields); - } - case IDLTypeIds.Func: { - return Func([], [], []); - } - case IDLTypeIds.Service: { - return Service({}); - } - default: - throw new Error('Illegal op_code: ' + entry[0]); - } - } - rawTable.forEach((entry, i) => { - const t = buildType(entry); - table[i].fill(t); - }); - - const types = rawTypes.map(t => getType(t)); - const output = retTypes.map((t, i) => { - return t.decodeValue(b, types[i]); - }); - - // skip unused values - for (let ind = retTypes.length; ind < types.length; ind++) { - types[ind].decodeValue(b, types[ind]); - } - - if (b.buffer.length > 0) { - throw new Error('decode: Left-over bytes'); - } - - return output; -} - -/** - * An Interface Factory, normally provided by a Candid code generation. - */ -export type InterfaceFactory = (idl: { - IDL: { - Empty: EmptyClass; - Reserved: ReservedClass; - Bool: BoolClass; - Null: NullClass; - Text: TextClass; - Int: IntClass; - Nat: NatClass; - - Float32: FloatClass; - Float64: FloatClass; - - Int8: FixedIntClass; - Int16: FixedIntClass; - Int32: FixedIntClass; - Int64: FixedIntClass; - - Nat8: FixedNatClass; - Nat16: FixedNatClass; - Nat32: FixedNatClass; - Nat64: FixedNatClass; - - Principal: PrincipalClass; - - Tuple: typeof Tuple; - Vec: typeof Vec; - Opt: typeof Opt; - Record: typeof Record; - Variant: typeof Variant; - Rec: typeof Rec; - Func: typeof Func; - - Service(t: Record): ServiceClass; - }; -}) => ServiceClass; - -// Export Types instances. -export const Empty = new EmptyClass(); -export const Reserved = new ReservedClass(); -export const Bool = new BoolClass(); -export const Null = new NullClass(); -export const Text = new TextClass(); -export const Int = new IntClass(); -export const Nat = new NatClass(); - -export const Float32 = new FloatClass(32); -export const Float64 = new FloatClass(64); - -export const Int8 = new FixedIntClass(8); -export const Int16 = new FixedIntClass(16); -export const Int32 = new FixedIntClass(32); -export const Int64 = new FixedIntClass(64); - -export const Nat8 = new FixedNatClass(8); -export const Nat16 = new FixedNatClass(16); -export const Nat32 = new FixedNatClass(32); -export const Nat64 = new FixedNatClass(64); - -export const Principal = new PrincipalClass(); - -export function Tuple(...types: T): TupleClass { - return new TupleClass(types); -} -export function Vec(t: Type): VecClass { - return new VecClass(t); -} -export function Opt(t: Type): OptClass { - return new OptClass(t); -} - -export function Record(t: Record): RecordClass { - return new RecordClass(t); -} -export function Variant(fields: Record) { - return new VariantClass(fields); -} -export function Rec() { - return new RecClass(); -} - -export function Func(args: Type[], ret: Type[], annotations: string[] = []) { - return new FuncClass(args, ret, annotations); -} - -export function Service(t: Record): ServiceClass { - return new ServiceClass(t); -} diff --git a/src/agent/javascript/src/index.ts b/src/agent/javascript/src/index.ts deleted file mode 100644 index 3c6168504b..0000000000 --- a/src/agent/javascript/src/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -export * from './actor'; -export * from './agent'; -export { - KeyPair, - SenderPubKey, - SenderSecretKey, - SenderSig, - generateKeyPair, - makeAuthTransform, - makeKeyPair, -} from './auth'; -export * from './http_agent_transforms'; -export * from './http_agent_types'; -export * from './principal'; -export * from './types'; -export * from './canisters/asset'; -export * from './canisters/management'; -export * from './candid'; - -import { Agent, HttpAgent } from './agent'; -import * as IDL from './idl'; -export { IDL }; - -// TODO The following modules will be a separate library for Candid -import * as UICore from './candid/candid-core'; -import * as UI from './candid/candid-ui'; -export { UICore, UI }; - -export interface GlobalInternetComputer { - ic: { - agent: Agent; - HttpAgent: typeof HttpAgent; - IDL: typeof IDL; - }; -} diff --git a/src/agent/javascript/src/principal.ts b/src/agent/javascript/src/principal.ts deleted file mode 100644 index 14568c0f26..0000000000 --- a/src/agent/javascript/src/principal.ts +++ /dev/null @@ -1,68 +0,0 @@ -import base32 from 'base32.js'; -import { SenderPubKey } from './auth'; -import { BinaryBlob, blobFromHex, blobFromUint8Array, blobToHex } from './types'; -import { getCrc32 } from './utils/getCrc'; -import { sha224 } from './utils/sha224'; - -const SELF_AUTHENTICATING_SUFFIX = 2; - -export class Principal { - public static selfAuthenticating(publicKey: SenderPubKey): Principal { - const sha = sha224(publicKey); - return new this(blobFromUint8Array(new Uint8Array([...sha, 2]))); - } - - public static fromHex(hex: string): Principal { - return new this(blobFromHex(hex)); - } - - public static fromText(text: string): Principal { - const canisterIdNoDash = text.toLowerCase().replace(/-/g, ''); - - const decoder = new base32.Decoder({ type: 'rfc4648', lc: false }); - const result = decoder.write(canisterIdNoDash).finalize(); - let arr = new Uint8Array(result); - arr = arr.slice(4, arr.length); - - return new this(blobFromUint8Array(arr)); - } - - public static fromBlob(blob: BinaryBlob): Principal { - return new this(blob); - } - - public readonly _isPrincipal = true; - - protected constructor(private _blob: BinaryBlob) {} - - public toBlob(): BinaryBlob { - return this._blob; - } - - public toHash() { - return this._blob; - } - - public toHex(): string { - return blobToHex(this._blob).toUpperCase(); - } - - public toText(): string { - const checksumArrayBuf = new ArrayBuffer(4); - const view = new DataView(checksumArrayBuf); - view.setUint32(0, getCrc32(this.toHex().toLowerCase()), false); - const checksum = Uint8Array.from(Buffer.from(checksumArrayBuf)); - - const bytes = Uint8Array.from(this._blob); - const array = new Uint8Array([...checksum, ...bytes]); - - const encoder = new base32.Encoder({ type: 'rfc4648', lc: false }); - const result = encoder.write(array).finalize().toLowerCase(); - const matches = result.match(/.{1,5}/g); - return matches ? matches.join('-') : ''; - } - - public toString() { - return this.toText(); - } -} diff --git a/src/agent/javascript/src/reject_code.ts b/src/agent/javascript/src/reject_code.ts deleted file mode 100644 index 9a6044d31f..0000000000 --- a/src/agent/javascript/src/reject_code.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum RejectCode { - SysFatal = 1, - SysTransient = 2, - DestinationInvalid = 3, - CanisterReject = 4, - CanisterError = 5, -} diff --git a/src/agent/javascript/src/request_id.test.ts b/src/agent/javascript/src/request_id.test.ts deleted file mode 100644 index 6cbb382ffa..0000000000 --- a/src/agent/javascript/src/request_id.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// tslint:disable-next-line: max-line-length -// https://github.com/dfinity-lab/dfinity/blob/5fef1450c9ab16ccf18381379149e504b11c8218/docs/spec/public/index.adoc#request-ids - -import { Buffer } from 'buffer/'; -import { SenderPubKey, SenderSig } from './auth'; -import { hash, requestIdOf } from './request_id'; -import { BinaryBlob, blobToHex } from './types'; - -const testHashOfBlob = async (input: BinaryBlob, expected: string) => { - const hashed = await hash(input); - const hex = blobToHex(hashed); - expect(hex).toBe(expected); -}; - -const testHashOfString = async (input: string, expected: string) => { - const encoded: Uint8Array = new TextEncoder().encode(input); - return testHashOfBlob(encoded as BinaryBlob, expected); -}; - -// This is based on the intermediate hashes of the request components from -// example in the spec. -test('hash', async () => { - await testHashOfString( - 'request_type', - '769e6f87bdda39c859642b74ce9763cdd37cb1cd672733e8c54efaa33ab78af9', - ); - await testHashOfString( - 'call', - '7edb360f06acaef2cc80dba16cf563f199d347db4443da04da0c8173e3f9e4ed', - ); - await testHashOfString( - 'callee', // The "canister_id" field was previously named "callee" - '92ca4c0ced628df1e7b9f336416ead190bd0348615b6f71a64b21d1b68d4e7e2', - ); - await testHashOfString( - 'canister_id', - '0a3eb2ba16702a387e6321066dd952db7a31f9b5cc92981e0a92dd56802d3df9', - ); - await testHashOfBlob( - Buffer.from([0, 0, 0, 0, 0, 0, 4, 210]) as BinaryBlob, - '4d8c47c3c1c837964011441882d745f7e92d10a40cef0520447c63029eafe396', - ); - await testHashOfString( - 'method_name', - '293536232cf9231c86002f4ee293176a0179c002daa9fc24be9bb51acdd642b6', - ); - await testHashOfString( - 'hello', - '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824', - ); - await testHashOfString('arg', 'b25f03dedd69be07f356a06fe35c1b0ddc0de77dcd9066c4be0c6bbde14b23ff'); - await testHashOfBlob( - Buffer.from([68, 73, 68, 76, 0, 253, 42]) as BinaryBlob, - '6c0b2ae49718f6995c02ac5700c9c789d7b7862a0d53e6d40a73f1fcd2f70189', - ); -}); - -// This is based on the example in the spec. -test('requestIdOf', async () => { - const request = { - request_type: 'call', - method_name: 'hello', - - // 0x00000000000004D2 - // \x00\x00\x00\x00\x00\x00\x04\xD2 - // 0 0 0 0 0 0 4 210 - canister_id: Buffer.from([0, 0, 0, 0, 0, 0, 4, 210]) as BinaryBlob, - - // DIDL\x00\xFD* - // D I D L \x00 \253 * - // 68 73 68 76 0 253 42 - arg: Buffer.from([68, 73, 68, 76, 0, 253, 42]) as BinaryBlob, - }; - - const requestId = await requestIdOf(request); - - expect(blobToHex(requestId)).toEqual( - '8781291c347db32a9d8c10eb62b710fce5a93be676474c42babc74c51858f94b', - ); -}); diff --git a/src/agent/javascript/src/request_id.ts b/src/agent/javascript/src/request_id.ts deleted file mode 100644 index deeec9b6da..0000000000 --- a/src/agent/javascript/src/request_id.ts +++ /dev/null @@ -1,76 +0,0 @@ -import borc from 'borc'; -import { Buffer } from 'buffer/'; -import { BinaryBlob, blobToHex } from './types'; -import { lebEncode } from './utils/leb128'; - -export type RequestId = BinaryBlob & { __requestId__: void }; -export function toHex(requestId: RequestId): string { - return blobToHex(requestId); -} - -export async function hash(data: BinaryBlob): Promise { - const hashed: ArrayBuffer = await crypto.subtle.digest( - { - name: 'SHA-256', - }, - data.buffer, - ); - return Buffer.from(hashed) as BinaryBlob; -} - -async function hashValue(value: unknown): Promise { - if (value instanceof borc.Tagged) { - return hashValue(value.value); - } else if (typeof value === 'string') { - return hashString(value); - } else if (typeof value === 'number') { - return hash(lebEncode(value) as BinaryBlob); - } else if (Buffer.isBuffer(value)) { - return hash(new Uint8Array(value) as BinaryBlob); - } else if (value instanceof Uint8Array || value instanceof ArrayBuffer) { - return hash(new Uint8Array(value) as BinaryBlob); - } else if ( - typeof value === 'object' && - value !== null && - typeof (value as any).toHash === 'function' - ) { - return Promise.resolve((value as any).toHash()).then(x => hashValue(x)); - } else if (value instanceof Promise) { - return value.then(x => hashValue(x)); - } else { - throw new Error(`Attempt to hash a value of unsupported type: ${value}`); - } -} - -const hashString = (value: string): Promise => { - const encoder = new TextEncoder(); - const encoded = encoder.encode(value); - return hash(Buffer.from(encoded) as BinaryBlob); -}; - -const concat = (bs: BinaryBlob[]): BinaryBlob => { - return bs.reduce((state: Uint8Array, b: BinaryBlob): Uint8Array => { - return new Uint8Array([...state, ...b]); - }, new Uint8Array()) as BinaryBlob; -}; - -export const requestIdOf = async (request: Record): Promise => { - const hashed: Array> = Object.entries(request).map( - async ([key, value]: [string, unknown]) => { - const hashedKey = await hashString(key); - const hashedValue = await hashValue(value); - - return [hashedKey, hashedValue] as [BinaryBlob, BinaryBlob]; - }, - ); - - const traversed: Array<[BinaryBlob, BinaryBlob]> = await Promise.all(hashed); - - const sorted: Array<[BinaryBlob, BinaryBlob]> = traversed.sort(([k1, v1], [k2, v2]) => { - return Buffer.compare(Buffer.from(k1), Buffer.from(k2)); - }); - - const concatenated: BinaryBlob = concat(sorted.map(concat)); - const requestId = (await hash(concatenated)) as RequestId; - return requestId; -}; diff --git a/src/agent/javascript/src/types.ts b/src/agent/javascript/src/types.ts deleted file mode 100644 index ad04cd7e09..0000000000 --- a/src/agent/javascript/src/types.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Buffer } from 'buffer/'; -import { lebEncode } from './utils/leb128'; - -export interface JsonArray extends Array {} -export interface JsonObject extends Record {} -export type JsonValue = boolean | string | number | JsonArray | JsonObject; - -// TODO -// Switch back to Uint8Array once hansl/simple-cbor provides deserialization - -// Named `BinaryBlob` as opposed to `Blob` so not to conflict with -// https://developer.mozilla.org/en-US/docs/Web/API/Blob -export type BinaryBlob = Buffer & { __BLOB: never }; - -export function blobFromUint8Array(arr: Uint8Array): BinaryBlob { - return Buffer.from(arr) as BinaryBlob; -} - -export function blobFromHex(hex: string): BinaryBlob { - return Buffer.from(hex, 'hex') as BinaryBlob; -} - -export function blobToHex(blob: BinaryBlob): string { - return blob.toString('hex'); -} - -// A Nonce that can be used for calls. -export type Nonce = BinaryBlob & { __nonce__: void }; - -export function makeNonce(): Nonce { - return lebEncode(+(+Date.now() + ('' + Math.random()).slice(2, 7))) as Nonce; -} diff --git a/src/agent/javascript/src/utils/getCrc.ts b/src/agent/javascript/src/utils/getCrc.ts deleted file mode 100644 index c31d6144a7..0000000000 --- a/src/agent/javascript/src/utils/getCrc.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { crc32 } from 'crc'; - -export function getCrc32(hex: string): number { - return crc32(Buffer.from(hex, 'hex')); -} diff --git a/src/agent/javascript/src/utils/hash.test.ts b/src/agent/javascript/src/utils/hash.test.ts deleted file mode 100644 index ab600dc2b8..0000000000 --- a/src/agent/javascript/src/utils/hash.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { idlLabelToId } from './hash'; - -test('IDL label', () => { - function testLabel(str: string, expected: number) { - expect(idlLabelToId(str)).toBe(expected); - } - - testLabel('', 0); - testLabel('id', 23515); - testLabel('description', 1595738364); - testLabel('short_name', 3261810734); - testLabel('Hi ☃', 1419229646); - testLabel('_0_', 0); - testLabel('_1_', 1); - testLabel('_+1_', 1055658234); - testLabel('_-1_', 1055757692); - testLabel('_123_', 123); - testLabel('_4294967295_', 4294967295); - testLabel('_4294967296_', 1569808370); - testLabel('_0xa_', 10); - testLabel('_0d_', 1055918252); - testLabel('_1.23_', 1360503298); - testLabel('_1e2_', 3552665568); - testLabel('_', 95); - testLabel('__', 21280); - testLabel('___', 4745535); -}); diff --git a/src/agent/javascript/src/utils/hash.ts b/src/agent/javascript/src/utils/hash.ts deleted file mode 100644 index f375cc08ff..0000000000 --- a/src/agent/javascript/src/utils/hash.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Hashes a string to a number. Algorithm can be found here: - * https://caml.inria.fr/pub/papers/garrigue-polymorphic_variants-ml98.pdf - * @param s - */ -function idlHash(s: string): number { - const utf8encoder = new TextEncoder(); - const array = utf8encoder.encode(s); - - let h = 0; - for (const c of array) { - h = (h * 223 + c) % 2 ** 32; - } - return h; -} - -export function idlLabelToId(label: string): number { - if (/^_\d+_$/.test(label) || /^_0x[0-9a-fA-F]+_$/.test(label)) { - const num = +label.slice(1, -1); - if (Number.isSafeInteger(num) && num >= 0 && num < 2 ** 32) { - return num; - } - } - return idlHash(label); -} diff --git a/src/agent/javascript/src/utils/leb128.test.ts b/src/agent/javascript/src/utils/leb128.test.ts deleted file mode 100644 index f3fdb9ce91..0000000000 --- a/src/agent/javascript/src/utils/leb128.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -import BigNumber from 'bignumber.js'; -import Pipe = require('buffer-pipe'); -import { Buffer } from 'buffer/'; -import { - lebDecode, - lebEncode, - readIntLE, - readUIntLE, - slebDecode, - slebEncode, - writeIntLE, - writeUIntLE, -} from './leb128'; - -test('leb', () => { - expect(lebEncode(0).toString('hex')).toBe('00'); - expect(lebEncode(7).toString('hex')).toBe('07'); - expect(lebEncode(127).toString('hex')).toBe('7f'); - expect(() => lebEncode(-1).toString('hex')).toThrow(); - expect(lebEncode(1).toString('hex')).toBe('01'); - expect(lebEncode(624485).toString('hex')).toBe('e58e26'); - expect(lebEncode(new BigNumber('1234567890abcdef1234567890abcdef', 16)).toString('hex')).toBe( - 'ef9baf8589cf959a92deb7de8a929eabb424', - ); - expect(lebEncode(new BigNumber('2000000')).toString('hex')).toBe('80897a'); - expect(lebEncode(new BigNumber('60000000000000000')).toString('hex')).toBe('808098f4e9b5ca6a'); - - expect(lebDecode(new Pipe(Buffer.from([0]))).toNumber()).toBe(0); - expect(lebDecode(new Pipe(Buffer.from([1]))).toNumber()).toBe(1); - expect(lebDecode(new Pipe(Buffer.from([0xe5, 0x8e, 0x26]))).toNumber()).toBe(624485); - expect( - lebDecode(new Pipe(Buffer.from('ef9baf8589cf959a92deb7de8a929eabb424', 'hex'))).toString(16), - ).toBe('1234567890abcdef1234567890abcdef'); -}); - -test('sleb', () => { - expect(slebEncode(-1).toString('hex')).toBe('7f'); - expect(slebEncode(-123456).toString('hex')).toBe('c0bb78'); - expect(slebEncode(42).toString('hex')).toBe('2a'); - expect(slebEncode(new BigNumber('1234567890abcdef1234567890abcdef', 16)).toString('hex')).toBe( - 'ef9baf8589cf959a92deb7de8a929eabb424', - ); - expect( - slebEncode(new BigNumber('1234567890abcdef1234567890abcdef', 16).negated()).toString('hex'), - ).toBe('91e4d0faf6b0eae5eda1c8a1f5ede1d4cb5b'); - expect(slebEncode(new BigNumber('2000000')).toString('hex')).toBe('8089fa00'); - expect(slebEncode(new BigNumber('60000000000000000')).toString('hex')).toBe('808098f4e9b5caea00'); - - expect(slebDecode(new Pipe(Buffer.from([0x7f]))).toNumber()).toBe(-1); - expect(slebDecode(new Pipe(Buffer.from([0xc0, 0xbb, 0x78]))).toNumber()).toBe(-123456); - expect(slebDecode(new Pipe(Buffer.from([0x2a]))).toNumber()).toBe(42); - expect( - slebDecode(new Pipe(Buffer.from('91e4d0faf6b0eae5eda1c8a1f5ede1d4cb5b', 'hex'))).toString(16), - ).toBe('-1234567890abcdef1234567890abcdef'); - expect(slebDecode(new Pipe(Buffer.from('808098f4e9b5caea00', 'hex'))).toString()).toBe( - '60000000000000000', - ); -}); - -test('IntLE', () => { - expect(writeIntLE(42, 2).toString('hex')).toBe('2a00'); - expect(writeIntLE(-42, 3).toString('hex')).toBe('d6ffff'); - expect(writeIntLE(1234567890, 5).toString('hex')).toBe('d202964900'); - expect(writeUIntLE(1234567890, 5).toString('hex')).toBe('d202964900'); - expect(writeIntLE(-1234567890, 5).toString('hex')).toBe('2efd69b6ff'); - expect(readIntLE(new Pipe(Buffer.from('d202964900', 'hex')), 5).toString()).toBe('1234567890'); - expect(readUIntLE(new Pipe(Buffer.from('d202964900', 'hex')), 5).toString()).toBe('1234567890'); - expect(readIntLE(new Pipe(Buffer.from('2efd69b6ff', 'hex')), 5).toString()).toBe('-1234567890'); - expect(readIntLE(new Pipe(Buffer.from('d6ffffffff', 'hex')), 5).toString()).toBe('-42'); - expect(readUIntLE(new Pipe(Buffer.from('d6ffffffff', 'hex')), 5).toString()).toBe( - '1099511627734', - ); -}); diff --git a/src/agent/javascript/src/utils/leb128.ts b/src/agent/javascript/src/utils/leb128.ts deleted file mode 100644 index 8735999354..0000000000 --- a/src/agent/javascript/src/utils/leb128.ts +++ /dev/null @@ -1,162 +0,0 @@ -// tslint:disable:no-bitwise -// Note: this file uses buffer-pipe, which on Node only, uses the Node Buffer -// implementation, which isn't compatible with the NPM buffer package -// which we use everywhere else. This means that we have to transform -// one into the other, hence why every function that returns a Buffer -// actually return `new Buffer(pipe.buffer)`. -// TODO: The best solution would be to have our own buffer type around -// Uint8Array which is standard. -import BigNumber from 'bignumber.js'; -import Pipe = require('buffer-pipe'); -import { Buffer } from 'buffer/'; - -export function safeRead(pipe: Pipe, num: number): Buffer { - if (pipe.buffer.length < num) { - throw new Error('unexpected end of buffer'); - } - return pipe.read(num); -} - -export function lebEncode(value: number | BigNumber): Buffer { - if (typeof value === 'number') { - value = new BigNumber(value); - } - value = value.integerValue(); - if (value.lt(0)) { - throw new Error('Cannot leb encode negative values.'); - } - - const pipe = new Pipe(); - while (true) { - const i = value.mod(0x80).toNumber(); - value = value.idiv(0x80); - if (value.eq(0)) { - pipe.write([i]); - break; - } else { - pipe.write([i | 0x80]); - } - } - - return new Buffer(pipe.buffer); -} - -export function lebDecode(pipe: Pipe): BigNumber { - let shift = 0; - let value = new BigNumber(0); - let byte; - - do { - byte = safeRead(pipe, 1)[0]; - value = value.plus(new BigNumber(byte & 0x7f).multipliedBy(new BigNumber(2).pow(shift))); - shift += 7; - } while (byte >= 0x80); - - return value; -} - -export function slebEncode(value: BigNumber | number): Buffer { - if (typeof value === 'number') { - value = new BigNumber(value); - } - value = value.integerValue(); - - const isNeg = value.lt(0); - if (isNeg) { - value = value.abs().minus(1); - } - const pipe = new Pipe(); - while (true) { - const i = getLowerBytes(value); - value = value.idiv(0x80); - if ((isNeg && value.eq(0) && (i & 0x40) !== 0) || (!isNeg && value.eq(0) && (i & 0x40) === 0)) { - pipe.write([i]); - break; - } else { - pipe.write([i | 0x80]); - } - } - - function getLowerBytes(num: BigNumber): number { - const bytes = num.mod(0x80).toNumber(); - if (isNeg) { - // We swap the bits here again, and remove 1 to do two's complement. - return 0x80 - bytes - 1; - } else { - return bytes; - } - } - return new Buffer(pipe.buffer); -} - -export function slebDecode(pipe: Pipe): BigNumber { - // Get the size of the buffer, then cut a buffer of that size. - const pipeView = new Uint8Array(pipe.buffer); - let len = 0; - for (; len < pipeView.byteLength; len++) { - if (pipeView[len] < 0x80) { - // If it's a positive number, we reuse lebDecode. - if ((pipeView[len] & 0x40) === 0) { - return lebDecode(pipe); - } - break; - } - } - - const bytes = new Uint8Array(safeRead(pipe, len + 1)); - let value = new BigNumber(0); - for (let i = bytes.byteLength - 1; i >= 0; i--) { - value = value.times(0x80).plus(0x80 - (bytes[i] & 0x7f) - 1); - } - return value.negated().minus(1); -} - -export function writeUIntLE(value: BigNumber | number, byteLength: number): Buffer { - if ((value instanceof BigNumber && value.isNegative()) || value < 0) { - throw new Error('Cannot write negative values.'); - } - return writeIntLE(value, byteLength); -} - -export function writeIntLE(value: BigNumber | number, byteLength: number): Buffer { - if (typeof value === 'number') { - value = new BigNumber(value); - } - value = value.integerValue(); - const pipe = new Pipe(); - let i = 0; - let mul = new BigNumber(256); - let sub = 0; - let byte = value.mod(mul).toNumber(); - pipe.write([byte]); - while (++i < byteLength) { - if (value.lt(0) && sub === 0 && byte !== 0) { - sub = 1; - } - byte = value.idiv(mul).minus(sub).mod(256).toNumber(); - pipe.write([byte]); - mul = mul.times(256); - } - return new Buffer(pipe.buffer); -} - -export function readUIntLE(pipe: Pipe, byteLength: number): BigNumber { - let val = new BigNumber(safeRead(pipe, 1)[0]); - let mul = new BigNumber(1); - let i = 0; - while (++i < byteLength) { - mul = mul.times(256); - const byte = safeRead(pipe, 1)[0]; - val = val.plus(mul.times(byte)); - } - return val; -} - -export function readIntLE(pipe: Pipe, byteLength: number): BigNumber { - let val = readUIntLE(pipe, byteLength); - const mul = new BigNumber(2).pow(8 * (byteLength - 1) + 7); - if (val.gte(mul)) { - val = val.minus(mul.times(2)); - } - return val; -} diff --git a/src/agent/javascript/src/utils/sha224.ts b/src/agent/javascript/src/utils/sha224.ts deleted file mode 100644 index 8cc55a5622..0000000000 --- a/src/agent/javascript/src/utils/sha224.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { sha224 as jsSha224 } from 'js-sha256'; -import { BinaryBlob, blobFromUint8Array } from '../types'; - -export function sha224(data: ArrayBuffer): BinaryBlob { - const shaObj = jsSha224.create(); - shaObj.update(data); - return blobFromUint8Array(new Uint8Array(shaObj.array())); -} diff --git a/src/agent/javascript/test-setup.js b/src/agent/javascript/test-setup.js deleted file mode 100644 index f2c1865c9c..0000000000 --- a/src/agent/javascript/test-setup.js +++ /dev/null @@ -1,12 +0,0 @@ -// This file may be used to polyfill features that aren't available in the test -// environment, i.e. JSDom. -// -// We sometimes need to do this because our target browsers are expected to have -// a feature that JSDom doesn't. -// -// Note that we can use webpack configuration to make some features available to -// Node.js in a similar way. - -window.crypto = require("@trust/webcrypto"); -window.TextEncoder = require("text-encoding").TextEncoder; -require("whatwg-fetch"); diff --git a/src/agent/javascript/tsconfig.json b/src/agent/javascript/tsconfig.json deleted file mode 100644 index 7e603fd39c..0000000000 --- a/src/agent/javascript/tsconfig.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "compilerOptions": { - /* Basic Options */ - "incremental": true, /* Enable incremental compilation */ - "target": "es2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ - "lib": [ - "dom", - "es2017" - ], /* Specify library files to be included in the compilation. */ - // "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - // "outDir": "out", /* Redirect output structure to the directory. */ - "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - "tsBuildInfoFile": "./build_info.json", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - "paths": { - "@dfinity/agent": ["src"] - }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "include": [ - "types/*", - "src/**/*.ts" - ] -} diff --git a/src/agent/javascript/tslint.json b/src/agent/javascript/tslint.json deleted file mode 100644 index 15853f509e..0000000000 --- a/src/agent/javascript/tslint.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "defaultSeverity": "error", - "extends": [ - "tslint:recommended" - ], - "jsRules": {}, - "linterOptions": { - "exclude": [ - "src/IDL.js", - "src/IDL.test.js" - ] - }, - "rules": { - "max-classes-per-file": false, - "interface-name": [true, "never-prefix"], - "no-consecutive-blank-lines": [true, 2], - "no-empty": [true, "allow-empty-functions"], - "no-switch-case-fall-through": true, - "object-literal-sort-keys": false, - "max-line-length": [true, 100], - "quotemark": [true, "single"], - "arrow-parens": [true, "ban-single-arg-parens"], - "space-before-function-paren": [false], - "variable-name": { - "options": [ - "ban-keywords", - "check-format", - "allow-leading-underscore", - "allow-pascal-case" - ] - } - }, - "rulesDirectory": [] -} diff --git a/src/agent/javascript/types/base32.d.ts b/src/agent/javascript/types/base32.d.ts deleted file mode 100644 index 9ac4d2dd40..0000000000 --- a/src/agent/javascript/types/base32.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -declare module 'base32.js' { - type Ret = { - finalize: () => any; - }; - - interface DecoderConfig { - type?: 'rfc4648' | 'crockford' | 'base32hex'; - alphabet?: string; - lc?: boolean; - } - class Decoder { - constructor(options?: DecoderConfig); - write(str: string): this; - finalize(str?: string): ArrayBuffer; - } - class Encoder { - private buf: ArrayBuffer; - private charmap: { [key: number]: number }; - constructor(options?: DecoderConfig); - write(buf: ArrayBuffer): this; - finalize(str?: ArrayBuffer): string; - } -} diff --git a/src/agent/javascript/types/borc.d.ts b/src/agent/javascript/types/borc.d.ts deleted file mode 100644 index 09ff4020aa..0000000000 --- a/src/agent/javascript/types/borc.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -declare module 'borc' { - import { Buffer } from 'buffer/'; - - class Decoder { - constructor(opts: { size: Number; tags: Record any> }); - - decodeFirst(input: ArrayBuffer): any; - } - - export function encode(o: any): Buffer | null; - - class Tagged { - tag: number; - value: any; - constructor(tag: Number, value: any); - } -} diff --git a/src/agent/javascript/types/buffer-pipe.d.ts b/src/agent/javascript/types/buffer-pipe.d.ts deleted file mode 100644 index 2b79bf30fe..0000000000 --- a/src/agent/javascript/types/buffer-pipe.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -declare module 'buffer-pipe' { - import { Buffer } from 'buffer/'; - - class BufferPipe { - readonly buffer: Buffer; - - /** - * Creates a new instance of a pipe - * @param {Buffer} buf - an optional buffer to start with - */ - constructor(buf?: Buffer); - - /** - * read `num` number of bytes from the pipe - * @param {Number} num - * @return {Buffer} - */ - read(num: number): Buffer; - - /** - * Wites a buffer to the pipe - * @param {Buffer} buf - */ - write(buf: Buffer | number[]): void; - - /** - * Whether or not there is more data to read from the buffer - * returns {Boolean} - */ - get end(): boolean; - - /** - * returns the number of bytes read from the stream - * @return {Integer} - */ - get bytesRead(): number; - - /** - * returns the number of bytes wrote to the stream - * @return {Integer} - */ - get bytesWrote(): number; - } - - export = BufferPipe; -} diff --git a/src/bootstrap/.gitignore b/src/bootstrap/.gitignore deleted file mode 100644 index 44e0e8dbad..0000000000 --- a/src/bootstrap/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -build_info.json -node_modules/ -dist/ -ts-out/ -**/*.js -**/*.js.map -**/*.d.ts - -# Cannot ignore candid.js, the last bastion of JS code in our app. -!src/candid/candid.js - -# Cannot ignore .d.ts files in types/ -!types/**/*.d.ts - -# Cannot ignore setup files for webpack and jest, which are still JavaScript. -!webpack.config.js -!jest.config.js -!test-setup.js diff --git a/src/bootstrap/.prettierrc b/src/bootstrap/.prettierrc deleted file mode 100644 index 4592d0205d..0000000000 --- a/src/bootstrap/.prettierrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "trailingComma": "all", - "tabWidth": 2, - "printWidth": 100, - "semi": true, - "bracketSpacing": true, - "useTabs": false, - "singleQuote": true, - "quoteProps": "consistent", - "arrowParens": "avoid" -} diff --git a/src/bootstrap/README.adoc b/src/bootstrap/README.adoc deleted file mode 100644 index 2f0912245d..0000000000 --- a/src/bootstrap/README.adoc +++ /dev/null @@ -1,46 +0,0 @@ -= Bootstrap Server - -== How to Run Locally - -Locally in your sdk repo, execute: - -. `npm install`. To install all Node dependencies. -. `npm run webpack -- --watch` will start webpack in watch mode. -. In two separate terminals in a DFX project (create one if needed); -.. Start a `dfx replica`. -.. Start `dfx bootstrap --root $SDK_REPO_PATH/src/bootstrap/dist/ --providers http://localhost:8080 --port 8000`. -. Open your browser to `http://localhost:8000`. Change code, wait a few seconds for webpack to - build, reload browser. - -If you need HTTPs (for example, using lvh or ic0.app using redirects), you will need to setup -your own nginx reverse proxy. Look up instructions online. - -**Note that HTTPS is needed for the crypto API if you're accessing a non-localhost URL. This is -a limitation of the web API (see -https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts/features_restricted_to_secure_contexts[ -the MDN documentation])**. - - - -== Startup Process -. The bootstrap server determines which worker host it is using; -.. If there is a query param `workerHost`, use that value. -.. If there is a `dfinity-ic-host` value in local storage, uses that value. -.. If the host ends with `localhost` and contains more than 1 subdomain, use `dfinity.localhost`. - _This is used to test cross-domain worker._ -.. If the host ends with `lvh.me`, use `dfinity.lvh.me`. _This is used to test cross-domain worker._ -.. If the host ends with `ic0.app`, use `dfinity.ic0.app`. -.. Otherwise, don't use a worker (this is for localhost and development purposes). - -. The bootstrap server determines the canister ID; -.. If there is a query param for `canisterId`, decode that value as text. -.. If there is a `dfinity-canister-id` value in local storage, uses that value. -.. If the host ends with `lvh.me`, split the host and use the first subdomain before - `ic0.app`. For example, `some-sub.01234567.lvh.me` would result in `01234567`. - _This is used to test cross-domain worker._ -.. If the host ends with `ic0.app`, split the host and use the first subdomain before - `ic0.app`. For example, `some-sub.01234567.ic0.app` would result in `01234567`. -.. Otherwise, show a UI for the user to enter a canister ID. - -. Create a worker with `${workerHost}/worker.js` using the same protocol. -. Get the canister's `/index.js` through the worker. diff --git a/src/bootstrap/README.html b/src/bootstrap/README.html deleted file mode 100644 index b72713e717..0000000000 --- a/src/bootstrap/README.html +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - - -Bootstrap Server - - - - - -
-
-

How to Run Locally

-
-
-

Locally in your sdk repo, execute:

-
-
-
    -
  1. -

    npm install. To install all Node dependencies.

    -
  2. -
  3. -

    npm run webpack — --watch will start webpack in watch mode.

    -
  4. -
  5. -

    In two separate terminals in a DFX project (create one if needed);

    -
    -
      -
    1. -

      Start a dfx replica.

      -
    2. -
    3. -

      Start dfx bootstrap --root $SDK_REPO_PATH/src/bootstrap/dist/ --providers http://localhost:8080 --port 8000.

      -
    4. -
    -
    -
  6. -
  7. -

    Open your browser to http://localhost:8000. Change code, wait a few seconds for webpack to -build, reload browser.

    -
  8. -
-
-
-

If you need HTTPs (for example, using lvh or ic0.app using redirects), you will need to setup -your own nginx reverse proxy. Look up instructions online.

-
-
-

Note that HTTPS is needed for the crypto API if you’re accessing a non-localhost URL. This is -a limitation of the web API (see ).

-
-
-
-
-

Startup Process

-
-
-
    -
  1. -

    The bootstrap server determines which worker host it is using;

    -
    -
      -
    1. -

      If there is a query param workerHost, use that value.

      -
    2. -
    3. -

      If there is a dfinity-ic-host value in local storage, uses that value.

      -
    4. -
    5. -

      If the host ends with localhost and contains more than 1 subdomain, use dfinity.localhost. -This is used to test cross-domain worker.

      -
    6. -
    7. -

      If the host ends with lvh.me, use dfinity.lvh.me. This is used to test cross-domain worker.

      -
    8. -
    9. -

      If the host ends with ic0.app, use dfinity.ic0.app.

      -
    10. -
    11. -

      Otherwise, don’t use a worker (this is for localhost and development purposes).

      -
    12. -
    -
    -
  2. -
  3. -

    The bootstrap server determines the canister ID;

    -
    -
      -
    1. -

      If there is a query param for canisterId, decode that value as text.

      -
    2. -
    3. -

      If there is a dfinity-canister-id value in local storage, uses that value.

      -
    4. -
    5. -

      If the host ends with lvh.me, split the host and use the first subdomain before -ic0.app. For example, some-sub.01234567.lvh.me would result in 01234567. -This is used to test cross-domain worker.

      -
    6. -
    7. -

      If the host ends with ic0.app, split the host and use the first subdomain before -ic0.app. For example, some-sub.01234567.ic0.app would result in 01234567.

      -
    8. -
    9. -

      Otherwise, show a UI for the user to enter a canister ID.

      -
    10. -
    -
    -
  4. -
  5. -

    Create a worker with ${workerHost}/worker.js using the same protocol.

    -
  6. -
  7. -

    Get the canister’s /index.js through the worker.

    -
  8. -
-
-
-
-
- - - \ No newline at end of file diff --git a/src/bootstrap/default.nix b/src/bootstrap/default.nix deleted file mode 100644 index b45658ad62..0000000000 --- a/src/bootstrap/default.nix +++ /dev/null @@ -1,49 +0,0 @@ -{ pkgs ? import ../../nix { inherit system; } -, system ? builtins.currentSystem -, agent-js ? import ../agent/javascript { inherit pkgs; } -}: -pkgs.napalm.buildPackage (pkgs.lib.noNixFiles (pkgs.lib.gitOnlySource ./.)) { - root = ./.; - name = "bootstrap-js"; - buildInputs = [ agent-js ]; - - outputs = [ "out" "lib" ]; - - propagatedNativeBuildInputs = [ - # Required by node-gyp - pkgs.python3 - ]; - propagatedBuildInputs = pkgs.lib.optional pkgs.stdenv.isDarwin - # Required by fsevents - pkgs.darwin.apple_sdk.frameworks.CoreServices; - - # ci script now does everything CI should do. Bundle is needed because it's the output - # of the nix derivation. - npmCommands = [ - "npm install" - ( - pkgs.writeScript "include-agent.sh" '' - #!${pkgs.stdenv.shell} - set -eo pipefail - - agent_node_modules="node_modules/@dfinity/agent" - mkdir -p $agent_node_modules - - tar xvzf ${agent-js.out}/dfinity-*.tgz --strip-component 1 --directory $agent_node_modules/ - cp -R ${agent-js.lib}/node_modules . - '' - ) - "npm run ci" - "npm run bundle" - ]; - - installPhase = '' - mkdir -p $out - - cp -R dist/* $out/ - - # Copy node_modules to be reused elsewhere. - mkdir -p $lib - cp -R node_modules $lib - ''; -} diff --git a/src/bootstrap/src/candid/candid.css b/src/bootstrap/src/candid/candid.css deleted file mode 100644 index e933b5c9d4..0000000000 --- a/src/bootstrap/src/candid/candid.css +++ /dev/null @@ -1,74 +0,0 @@ -.signature { - font-size: 15px; - font-weight: 400; - margin: 5px; -} -.argument, .result, .status, .composite { - background-color: #F9F9F9; - border: 1px solid #E5E5E5; - color: #545454; - font-family: monospace; - font-size: 15px; - font-weight: 400; - height: auto; - margin-right: 10px; - margin-bottom: 10px; -} -.open { - margin: 5px; -} -.reject { - border: 1px solid #cc0000; -} -.result { - display: none; -} -.error { - color: #cc0000; -} -.status { - color: #cc0000; - display: none; -} -.left { - text-align: left; - width: 84%; - display: inline-block; - overflow-wrap: break-word; -} -.right { - text-align: right; - width: 15%; - display: inline-block; -} -.btn { - background-color: #02ADEA; - border-color: #02ADEA; - border-radius: .25rem; - color: #FFF; - font-family: sans-serif; - font-size: 16px; - font-weight: 700; - margin: 5px; -} -.popup-form { - border: 1px solid #E5E5E5; - padding-top: 10px; - padding-left: 10px; -} -.console { - display: flex; - flex: 1; - flex-direction: column; - font-family: monospace; - background-color: #F9F9F9; - color: #545454; -} -.console-line { - overflow-wrap: break-word; - flex: 0; - flex-basis: auto; - border: 0; - margin-left: 5px; - margin-bottom: 5px; -} diff --git a/src/bootstrap/src/candid/candid.html b/src/bootstrap/src/candid/candid.html deleted file mode 100644 index 952398d4e7..0000000000 --- a/src/bootstrap/src/candid/candid.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - DFINITY Canister Candid UI - - - -

Service

-
- This service has the following methods: -
    -
-
-
- - diff --git a/src/bootstrap/src/candid/candid.ts b/src/bootstrap/src/candid/candid.ts deleted file mode 100644 index e06e6a50bc..0000000000 --- a/src/bootstrap/src/candid/candid.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { Actor, IDL, InputBox, Principal, UI } from '@dfinity/agent'; -import './candid.css'; - -class CanisterActor extends Actor { - [x: string]: (...args: unknown[]) => Promise; -} - -export function render(id: Principal, canister: CanisterActor) { - document.getElementById('title')!.innerText = `Service ${id}`; - for (const [name, func] of Actor.interfaceOf(canister)._fields) { - renderMethod(canister, name, func); - } - const consoleEl = document.createElement('div'); - consoleEl.className = 'console'; - document.body.appendChild(consoleEl); -} - -function renderMethod(canister: CanisterActor, name: string, idlFunc: IDL.FuncClass) { - const item = document.createElement('li'); - - const sig = document.createElement('div'); - sig.className = 'signature'; - sig.innerHTML = `${name}: ${idlFunc.display()}`; - item.appendChild(sig); - - const inputs: InputBox[] = []; - idlFunc.argTypes.forEach((arg, i) => { - const inputbox = UI.renderInput(arg); - inputs.push(inputbox); - inputbox.render(item); - }); - - const button = document.createElement('button'); - button.className = 'btn'; - if (idlFunc.annotations.includes('query')) { - button.innerText = 'Query'; - } else { - button.innerText = 'Call'; - } - item.appendChild(button); - - const random = document.createElement('button'); - random.className = 'btn'; - random.innerText = 'Lucky'; - item.appendChild(random); - - const resultDiv = document.createElement('div'); - resultDiv.className = 'result'; - const left = document.createElement('span'); - left.className = 'left'; - const right = document.createElement('span'); - right.className = 'right'; - resultDiv.appendChild(left); - resultDiv.appendChild(right); - item.appendChild(resultDiv); - - const list = document.getElementById('methods')!; - list.append(item); - - async function call(args: any[]) { - left.className = 'left'; - left.innerText = 'Waiting...'; - right.innerText = ''; - resultDiv.style.display = 'block'; - - const tStart = Date.now(); - const result = await canister[name](...args); - const duration = (Date.now() - tStart) / 1000; - right.innerText = `(${duration}s)`; - return result; - } - - function callAndRender(args: any[]) { - (async () => { - const callResult = await call(args); - let result: any; - if (idlFunc.retTypes.length === 0) { - result = []; - } else if (idlFunc.retTypes.length === 1) { - result = [callResult]; - } else { - result = callResult; - } - left.innerHTML = ''; - - const containers: HTMLDivElement[] = []; - const textContainer = document.createElement('div'); - containers.push(textContainer); - left.appendChild(textContainer); - const text = encodeStr(IDL.FuncClass.argsToString(idlFunc.retTypes, result)); - textContainer.innerHTML = text; - const showArgs = encodeStr(IDL.FuncClass.argsToString(idlFunc.argTypes, args)); - log(`› ${name}${showArgs}`); - log(text); - - const uiContainer = document.createElement('div'); - containers.push(uiContainer); - uiContainer.style.display = 'none'; - left.appendChild(uiContainer); - idlFunc.retTypes.forEach((arg, ind) => { - const box = UI.renderInput(arg); - box.render(uiContainer); - UI.renderValue(arg, box, result[ind]); - }); - - const jsonContainer = document.createElement('div'); - containers.push(jsonContainer); - jsonContainer.style.display = 'none'; - left.appendChild(jsonContainer); - jsonContainer.innerText = JSON.stringify(callResult); - - let i = 0; - left.addEventListener('click', () => { - containers[i].style.display = 'none'; - i = (i + 1) % 3; - containers[i].style.display = 'block'; - }); - })().catch(err => { - left.className += ' error'; - left.innerText = err.message; - throw err; - }); - } - - random.addEventListener('click', () => { - const args = inputs.map(arg => arg.parse({ random: true })); - const isReject = inputs.some(arg => arg.isRejected()); - if (isReject) { - return; - } - callAndRender(args); - }); - - button.addEventListener('click', () => { - const args = inputs.map(arg => arg.parse()); - const isReject = inputs.some(arg => arg.isRejected()); - if (isReject) { - return; - } - callAndRender(args); - }); -} - -function encodeStr(str: string) { - const escapeChars: Record = { - ' ': ' ', - '<': '<', - '>': '>', - '\n': '
', - }; - const regex = new RegExp('[ <>\n]', 'g'); - return str.replace(regex, m => { - return escapeChars[m]; - }); -} - -function log(content: Element | string) { - const consoleEl = document.getElementsByClassName('console')[0]; - const line = document.createElement('div'); - line.className = 'console-line'; - if (content instanceof Element) { - line.appendChild(content); - } else { - line.innerHTML = content; - } - consoleEl.appendChild(line); -} diff --git a/src/bootstrap/src/dfinity.png b/src/bootstrap/src/dfinity.png deleted file mode 100644 index a8a7568b3b..0000000000 Binary files a/src/bootstrap/src/dfinity.png and /dev/null differ diff --git a/src/bootstrap/src/host.ts b/src/bootstrap/src/host.ts deleted file mode 100644 index 0e52adbddf..0000000000 --- a/src/bootstrap/src/host.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { - Agent, - HttpAgent, - makeAuthTransform, - makeNonceTransform, - Principal, - ProxyAgent, - ProxyMessage, -} from '@dfinity/agent'; -import { SiteInfo } from './site'; - -export async function createAgent(site: SiteInfo): Promise { - const workerHost = site.isUnknown() ? undefined : await site.getWorkerHost(); - const host = await site.getHost(); - - if (!workerHost) { - const keyPair = await site.getKeyPair(); - const principal = Principal.selfAuthenticating(keyPair.publicKey); - const creds = await site.getLogin(); - const agent = new HttpAgent({ - host, - principal, - ...(creds && { credentials: { name: creds[0], password: creds[1] } }), - }); - agent.addTransform(makeNonceTransform()); - agent.setAuthTransform(makeAuthTransform(keyPair)); - - return agent; - } else { - return createWorkerAgent(site, workerHost, host); - } -} - -async function createWorkerAgent(site: SiteInfo, workerHost: string, host: string): Promise { - // Create the IFRAME. - let messageQueue: ProxyMessage[] | null = []; - let loaded = false; - const agent = new ProxyAgent((msg: ProxyMessage) => { - if (!loaded) { - if (!messageQueue) { - throw new Error('No Message Queue but need Queueing...'); - } - messageQueue.push(msg); - } else { - iframeEl.contentWindow!.postMessage(msg, '*'); - } - }); - - const iframeEl = document.createElement('iframe'); - - iframeEl.src = `${workerHost}/worker.html?${host ? 'host=' + encodeURIComponent(host) : ''}`; - window.addEventListener('message', ev => { - if (ev.origin === workerHost) { - switch (ev.data) { - case 'ready': - const q = messageQueue?.splice(0, messageQueue.length) || []; - for (const msg of q) { - iframeEl.contentWindow!.postMessage(msg, workerHost); - } - - loaded = true; - messageQueue = null; - break; - - case 'login': - const url = new URL(workerHost); - url.pathname = '/login.html'; - url.searchParams.append('redirect', '' + window.location); - window.location.replace('' + url); - break; - - default: - if (typeof ev.data === 'object') { - agent.onmessage(ev.data); - } else { - throw new Error('Invalid message from worker: ' + JSON.stringify(ev.data)); - } - } - } - }); - - document.head.append(iframeEl); - return agent; -} diff --git a/src/bootstrap/src/index.html b/src/bootstrap/src/index.html deleted file mode 100644 index 8c7387d19f..0000000000 --- a/src/bootstrap/src/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - IC Canister Bootstrap - - - - - Loading... - - - diff --git a/src/bootstrap/src/index.ts b/src/bootstrap/src/index.ts deleted file mode 100644 index 72a535e2f7..0000000000 --- a/src/bootstrap/src/index.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { - createAssetCanisterActor, - GlobalInternetComputer, - HttpAgent, - IDL, - Principal, -} from '@dfinity/agent'; -import { createAgent } from './host'; -import { SiteInfo } from './site'; - -declare const window: GlobalInternetComputer & Window; - -// Retrieve and execute a JavaScript file from the server. -async function _loadJs( - canisterId: Principal, - filename: string, - onload = async () => {}, -): Promise { - const actor = createAssetCanisterActor({ canisterId }); - const content = await actor.retrieve(filename); - const js = new TextDecoder().decode(new Uint8Array(content)); - // const dataUri = new Function(js); - - // Run an event function so the callee can execute some code before loading the - // Javascript. - await onload(); - - // TODO(hansl): either get rid of eval, or rid of webpack, or make this - // work without this horrible hack. - return eval(js); // tslint:disable-line -} - -async function _loadCandid(canisterId: Principal): Promise { - const origin = window.location.origin; - const url = `${origin}/_/candid?canisterId=${canisterId.toText()}&format=js`; - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Cannot fetch candid file`); - } - const js = await response.text(); - const dataUri = 'data:text/javascript;charset=utf-8,' + encodeURIComponent(js); - // TODO(hansl): either get rid of eval, or rid of webpack, or make this - // work without this horrible hack. - return eval('import("' + dataUri + '")'); // tslint:disable-line -} - -async function _main() { - const site = await SiteInfo.fromWindow(); - const agent = await createAgent(site); - window.ic = { agent, HttpAgent, IDL }; - - // Find the canister ID. Allow override from the url with 'canister_id=1234..' - const canisterId = site.principal; - if (!canisterId) { - // Show an error. - const div = document.createElement('div'); - div.innerText = - 'Could not find the canister ID to use. Please provide one in the query parameters.'; - - document.body.replaceChild(div, document.body.getElementsByTagName('app').item(0)!); - } else { - if (window.location.pathname === '/candid') { - // Load candid.did.js from endpoint. - const candid = await _loadCandid(canisterId); - const canister = window.ic.agent.makeActorFactory(candid.default)({ canisterId }); - const render = await import('./candid/candid'); - render.render(canisterId, canister); - } else { - // Load index.js from the canister and execute it. - await _loadJs(canisterId, 'index.js', async () => { - document.getElementById('ic-progress')!.remove(); - }); - } - } -} - -_main().catch(err => { - const div = document.createElement('div'); - div.innerText = 'An error happened:'; - const pre = document.createElement('pre'); - pre.innerHTML = err.stack; - div.appendChild(pre); - document.body.replaceChild(div, document.body.getElementsByTagName('app').item(0)!); - throw err; -}); diff --git a/src/bootstrap/src/login.html b/src/bootstrap/src/login.html deleted file mode 100644 index cc13c6c0fd..0000000000 --- a/src/bootstrap/src/login.html +++ /dev/null @@ -1,18 +0,0 @@ - - -
Login is necessary to access this network:
- -
-
- - -
-
- - -
-
- -
- - diff --git a/src/bootstrap/src/login.ts b/src/bootstrap/src/login.ts deleted file mode 100644 index 77e19af8ba..0000000000 --- a/src/bootstrap/src/login.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { SiteInfo } from './site'; - -const loginEl = document.getElementById('login')!; -const usernameEl = document.getElementById('username')! as HTMLInputElement; -const passwordEl = document.getElementById('password')! as HTMLInputElement; - -SiteInfo.fromWindow().then(site => { - site.getLogin().then(login => { - if (login) { - const [user, pass] = login; - usernameEl.value = user; - passwordEl.value = pass; - } - }); - - loginEl.addEventListener('click', async () => { - await site.setLogin(usernameEl.value, passwordEl.value); - - const url = new URL(window.location + ''); - const redirect = url.searchParams.get('redirect'); - - if (redirect) { - // console.log(redirect); - window.location.replace(redirect); - } else { - alert('Login credentials saved.'); - } - }); -}); diff --git a/src/bootstrap/src/site.ts b/src/bootstrap/src/site.ts deleted file mode 100644 index 4fea8e14bf..0000000000 --- a/src/bootstrap/src/site.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { generateKeyPair, KeyPair, makeKeyPair, Principal } from '@dfinity/agent'; -import localforage from 'localforage'; -import * as storage from './storage'; - -const localStorageCanisterIdKey = 'dfinity-ic-canister-id'; -const localStorageHostKey = 'dfinity-ic-host'; -const localStorageIdentityKey = 'dfinity-ic-user-identity'; -const localStorageLoginKey = 'dfinity-ic-login'; - -async function _getVariable(name: string, localStorageName: string): Promise; -async function _getVariable( - name: string, - localStorageName: string, - defaultValue: string, -): Promise; -async function _getVariable( - name: string, - localStorageName: string, - defaultValue?: string, -): Promise { - const params = new URLSearchParams(window.location.search); - - const maybeValue = params.get(name); - if (maybeValue) { - return maybeValue; - } - - const lsValue = await storage.retrieve(localStorageName); - if (lsValue) { - return lsValue; - } - - return defaultValue; -} - -function getCanisterId(s: string | undefined): Principal | undefined { - if (s === undefined) { - return undefined; - } else { - try { - return Principal.fromText(s); - } catch (_) { - return undefined; - } - } -} - -export enum DomainKind { - Unknown, - Localhost, - Ic0, - Lvh, -} - -export class SiteInfo { - public static async worker(): Promise { - const siteInfo = await SiteInfo.fromWindow(); - siteInfo._isWorker = true; - - return siteInfo; - } - - public static async unknown(): Promise { - const principal = await _getVariable('canisterId', localStorageCanisterIdKey); - return new SiteInfo( - DomainKind.Unknown, - principal !== undefined ? Principal.fromText(principal) : undefined, - ); - } - - public static async fromWindow(): Promise { - const { hostname } = window.location; - const components = hostname.split('.'); - const [maybeCId, maybeIc0, maybeApp] = components.slice(-3); - const subdomain = components.slice(0, -3).join('.'); - - if (maybeIc0 === 'ic0' && maybeApp === 'app') { - return new SiteInfo(DomainKind.Ic0, getCanisterId(maybeCId), subdomain); - } else if (maybeIc0 === 'lvh' && maybeApp === 'me') { - return new SiteInfo(DomainKind.Lvh, getCanisterId(maybeCId), subdomain); - } else if (maybeIc0 === 'localhost' && maybeApp === undefined) { - /// Allow subdomain of localhost. - return new SiteInfo(DomainKind.Localhost, getCanisterId(maybeCId), subdomain); - } else if (maybeApp === 'localhost') { - /// Allow subdomain of localhost, but maybeIc0 is the canister ID. - return new SiteInfo( - DomainKind.Localhost, - getCanisterId(maybeIc0), - `${maybeCId}.${subdomain}`, - ); - } else { - return this.unknown(); - } - } - - private _isWorker = false; - - constructor( - public readonly kind: DomainKind, - public readonly principal?: Principal, - public readonly subdomain = '', - ) {} - - public async setLogin(username: string, password: string): Promise { - await this.store(localStorageLoginKey, JSON.stringify([username, password])); - } - - public async getLogin(): Promise<[string, string] | undefined> { - const maybeCreds = await this.retrieve(localStorageLoginKey); - return maybeCreds !== undefined ? JSON.parse(maybeCreds) : undefined; - } - - public async getKeyPair(): Promise { - let k = await _getVariable('userIdentity', localStorageIdentityKey); - if (k === undefined) { - k = await this.retrieve(localStorageIdentityKey); - } - - if (k) { - const kp = JSON.parse(k); - return makeKeyPair(new Uint8Array(kp.publicKey.data), new Uint8Array(kp.secretKey.data)); - } else { - const kp = generateKeyPair(); - await this.store(localStorageIdentityKey, JSON.stringify(kp)); - - return kp; - } - } - - public isUnknown() { - return this.kind === DomainKind.Unknown; - } - - public async getWorkerHost(): Promise { - if (this._isWorker) { - return ''; - } - - const { port, protocol } = window.location; - - switch (this.kind) { - case DomainKind.Unknown: - throw new Error('Cannot get worker host inside a worker.'); - case DomainKind.Ic0: - return `${protocol}//z.ic0.app${port ? ':' + port : ''}`; - case DomainKind.Lvh: - return `${protocol}//z.lvh.me${port ? ':' + port : ''}`; - case DomainKind.Localhost: - return `${protocol}//z.localhost${port ? ':' + port : ''}`; - } - } - - public async getHost(): Promise { - // Figure out the host. - let host = await _getVariable('host', localStorageHostKey, ''); - - if (host) { - try { - host = JSON.parse(host); - - if (Array.isArray(host)) { - return '' + host[Math.floor(Math.random() * host.length)]; - } else { - return '' + host; - } - } catch (_) { - return host; - } - } else { - const { port, protocol } = window.location; - - switch (this.kind) { - case DomainKind.Unknown: - return ''; - case DomainKind.Ic0: - // TODO: think if we want to have this hard coded here. We might. - return `${protocol}//gw.dfinity.network${port ? ':' + port : ''}`; - case DomainKind.Lvh: - return `${protocol}//r.lvh.me${port ? ':' + port : ''}`; - case DomainKind.Localhost: - return `${protocol}//r.localhost${port ? ':' + port : ''}`; - default: - return host || ''; - } - } - } - - private async store(name: string, value: string): Promise { - await localforage.setItem(name, value); - await storage.store(name, value); - } - - private async retrieve(name: string): Promise { - const maybeValue = await storage.retrieve(name); - if (maybeValue === undefined) { - return localforage.getItem(name); - } else { - return maybeValue; - } - } -} diff --git a/src/bootstrap/src/storage.ts b/src/bootstrap/src/storage.ts deleted file mode 100644 index 3f83527a46..0000000000 --- a/src/bootstrap/src/storage.ts +++ /dev/null @@ -1,29 +0,0 @@ -async function parse(): Promise> { - const cookie = document.cookie; - const result = Object(null); - - for (const kvPair of cookie.trim().split(';')) { - const [key, value] = kvPair - .trim() - .split('=', 2) - .map(x => x.trim()); - - try { - if (value !== undefined) { - result[key] = decodeURIComponent(value); - } - } catch (_) { - // Do Nothing. - } - } - - return result; -} - -export async function store(name: string, value: string): Promise { - document.cookie = `${name}=${encodeURIComponent(value)};max-age=31536000;secure`; // a year. -} - -export async function retrieve(name: string): Promise { - return (await parse())[name] || undefined; -} diff --git a/src/bootstrap/src/worker.html b/src/bootstrap/src/worker.html deleted file mode 100644 index d3a3d8abf0..0000000000 --- a/src/bootstrap/src/worker.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/bootstrap/src/worker.ts b/src/bootstrap/src/worker.ts deleted file mode 100644 index f72be309f5..0000000000 --- a/src/bootstrap/src/worker.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ProxyMessageKind, ProxyStubAgent } from '@dfinity/agent'; -import { createAgent } from './host'; -import { SiteInfo } from './site'; - -async function bootstrap() { - const agent = await createAgent(await SiteInfo.worker()); - (window as any).ic = { - agent, - }; - const stub = new ProxyStubAgent(msg => { - switch (msg.type) { - case ProxyMessageKind.CallResponse: - const response = msg.response.response; - msg.response.response = JSON.parse(JSON.stringify(response)); - } - window.parent.postMessage(msg, '*'); - }, agent); - - window.addEventListener('message', ev => { - stub.onmessage(ev.data); - }); - - // Ping the server, and if it works send our ACK message to the parent. - // If it doesn't work because of a 401 UNAUTHORIZED code, send a login - // message to tell the parent we need to login. - agent - .status() - .then(_json => { - window.parent.postMessage('ready', '*'); - }) - .catch((error: Error) => { - if (error.message.includes('Code: 401')) { - window.parent.postMessage('login', '*'); - } else { - throw error; - } - }); -} - -bootstrap().catch(error => { - (console as any).error(error); - window.parent.postMessage({ error }, '*'); -}); diff --git a/src/bootstrap/tsconfig.json b/src/bootstrap/tsconfig.json deleted file mode 100644 index 70cd0bf43d..0000000000 --- a/src/bootstrap/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "compilerOptions": { - "incremental": true, - "allowJs": false, - "outDir": "ts-out/", - "target": "ES2017", - "module": "commonjs", - "lib": [ - "dom", - "es2017" - ], - "sourceMap": true, - "strict": true, - "paths": { - "@dfinity/agent": [ - "../../src/agent/javascript/src", - "node_modules/@dfinity/agent" - ] - }, - "baseUrl": "./", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true - }, - "include": [ - "types/*", - "src/**/*.ts" - ] -} diff --git a/src/bootstrap/tslint.json b/src/bootstrap/tslint.json deleted file mode 100644 index 15853f509e..0000000000 --- a/src/bootstrap/tslint.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "defaultSeverity": "error", - "extends": [ - "tslint:recommended" - ], - "jsRules": {}, - "linterOptions": { - "exclude": [ - "src/IDL.js", - "src/IDL.test.js" - ] - }, - "rules": { - "max-classes-per-file": false, - "interface-name": [true, "never-prefix"], - "no-consecutive-blank-lines": [true, 2], - "no-empty": [true, "allow-empty-functions"], - "no-switch-case-fall-through": true, - "object-literal-sort-keys": false, - "max-line-length": [true, 100], - "quotemark": [true, "single"], - "arrow-parens": [true, "ban-single-arg-parens"], - "space-before-function-paren": [false], - "variable-name": { - "options": [ - "ban-keywords", - "check-format", - "allow-leading-underscore", - "allow-pascal-case" - ] - } - }, - "rulesDirectory": [] -} diff --git a/src/bootstrap/types/base32.d.ts b/src/bootstrap/types/base32.d.ts deleted file mode 100644 index 9ac4d2dd40..0000000000 --- a/src/bootstrap/types/base32.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -declare module 'base32.js' { - type Ret = { - finalize: () => any; - }; - - interface DecoderConfig { - type?: 'rfc4648' | 'crockford' | 'base32hex'; - alphabet?: string; - lc?: boolean; - } - class Decoder { - constructor(options?: DecoderConfig); - write(str: string): this; - finalize(str?: string): ArrayBuffer; - } - class Encoder { - private buf: ArrayBuffer; - private charmap: { [key: number]: number }; - constructor(options?: DecoderConfig); - write(buf: ArrayBuffer): this; - finalize(str?: ArrayBuffer): string; - } -} diff --git a/src/bootstrap/types/borc.d.ts b/src/bootstrap/types/borc.d.ts deleted file mode 100644 index 09ff4020aa..0000000000 --- a/src/bootstrap/types/borc.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -declare module 'borc' { - import { Buffer } from 'buffer/'; - - class Decoder { - constructor(opts: { size: Number; tags: Record any> }); - - decodeFirst(input: ArrayBuffer): any; - } - - export function encode(o: any): Buffer | null; - - class Tagged { - tag: number; - value: any; - constructor(tag: Number, value: any); - } -} diff --git a/src/bootstrap/types/buffer-pipe.d.ts b/src/bootstrap/types/buffer-pipe.d.ts deleted file mode 100644 index 2b79bf30fe..0000000000 --- a/src/bootstrap/types/buffer-pipe.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -declare module 'buffer-pipe' { - import { Buffer } from 'buffer/'; - - class BufferPipe { - readonly buffer: Buffer; - - /** - * Creates a new instance of a pipe - * @param {Buffer} buf - an optional buffer to start with - */ - constructor(buf?: Buffer); - - /** - * read `num` number of bytes from the pipe - * @param {Number} num - * @return {Buffer} - */ - read(num: number): Buffer; - - /** - * Wites a buffer to the pipe - * @param {Buffer} buf - */ - write(buf: Buffer | number[]): void; - - /** - * Whether or not there is more data to read from the buffer - * returns {Boolean} - */ - get end(): boolean; - - /** - * returns the number of bytes read from the stream - * @return {Integer} - */ - get bytesRead(): number; - - /** - * returns the number of bytes wrote to the stream - * @return {Integer} - */ - get bytesWrote(): number; - } - - export = BufferPipe; -} diff --git a/src/bootstrap/webpack.config.js b/src/bootstrap/webpack.config.js deleted file mode 100644 index 8b9f6f0991..0000000000 --- a/src/bootstrap/webpack.config.js +++ /dev/null @@ -1,85 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const TerserPlugin = require('terser-webpack-plugin'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); - -module.exports = { - mode: 'production', - entry: { - bootstrap: './src/index.ts', - candid: './src/candid/candid.ts', - login: './src/login.ts', - worker: './src/worker.ts', - }, - target: 'web', - output: { - // This is necessary to allow internal apps to bundle their own code with - // webpack which may conflict with us. - jsonpFunction: '__dfinityJsonp', - path: path.resolve(__dirname, './dist'), - filename: '[name].js', - }, - resolve: { - plugins: [new TsconfigPathsPlugin({ configFile: './tsconfig.json' })], - extensions: ['.tsx', '.ts', '.js'], - }, - devtool: 'source-map', - optimization: { - minimize: true, - minimizer: [ - new TerserPlugin({ - cache: true, - parallel: true, - sourceMap: true, // Must be set to true if using source-maps in production - terserOptions: { - ecma: 8, - minimize: true, - comments: false, - // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions - }, - }), - ], - }, - module: { - rules: [ - { - test: /\.css$/, - use: ['style-loader', 'css-loader'], - }, - { - test: /\.tsx?$/, - use: ['ts-loader'], - }, - ], - }, - plugins: [ - new HtmlWebpackPlugin({ - template: 'src/index.html', - filename: 'index.html', - chunks: ['bootstrap'], - }), - new HtmlWebpackPlugin({ - template: 'src/worker.html', - filename: 'worker.html', - chunks: ['worker'], - }), - new HtmlWebpackPlugin({ - template: 'src/candid/candid.html', - filename: 'candid/index.html', - chunks: ['bootstrap', 'candid'], - }), - new HtmlWebpackPlugin({ - template: 'src/login.html', - filename: 'login.html', - chunks: ['login'], - }), - new CopyWebpackPlugin([ - { - from: 'src/dfinity.png', - to: 'favicon.ico', - }, - ]), - ], -};