From 913d6d8bd069609ab9e4fd7e9333ec0ea5cef0e7 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Fri, 16 Mar 2018 12:10:13 +0100 Subject: [PATCH] Add basic mock provider (#58) --- package.json | 2 +- packages/api-provider/src/mock/index.js | 29 ++++ packages/api-provider/src/mock/mocks.js | 33 +++++ packages/api-provider/src/mock/send.js | 10 ++ packages/api-provider/src/mock/state.js | 35 +++++ packages/api-provider/src/mock/state.spec.js | 33 +++++ packages/api-provider/src/mock/subscribe.js | 25 ++++ .../api-provider/src/mock/subscribe.spec.js | 44 +++++++ packages/api-provider/src/mock/types.js | 26 ++++ packages/api-provider/src/mock/unsubscribe.js | 21 +++ .../api-provider/src/mock/unsubscribe.spec.js | 45 +++++++ yarn.lock | 124 +++++++++++++++--- 12 files changed, 410 insertions(+), 17 deletions(-) create mode 100644 packages/api-provider/src/mock/index.js create mode 100644 packages/api-provider/src/mock/mocks.js create mode 100644 packages/api-provider/src/mock/send.js create mode 100644 packages/api-provider/src/mock/state.js create mode 100644 packages/api-provider/src/mock/state.spec.js create mode 100644 packages/api-provider/src/mock/subscribe.js create mode 100644 packages/api-provider/src/mock/subscribe.spec.js create mode 100644 packages/api-provider/src/mock/types.js create mode 100644 packages/api-provider/src/mock/unsubscribe.js create mode 100644 packages/api-provider/src/mock/unsubscribe.spec.js diff --git a/package.json b/package.json index c94e55a7d2..c4e3779e69 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "test": "jest --coverage" }, "devDependencies": { - "@polkadot/dev": "^0.16.17", + "@polkadot/dev": "^0.16.19", "lerna": "^2.5.1" } } diff --git a/packages/api-provider/src/mock/index.js b/packages/api-provider/src/mock/index.js new file mode 100644 index 0000000000..f22c10ee2a --- /dev/null +++ b/packages/api-provider/src/mock/index.js @@ -0,0 +1,29 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. +// @flow + +import type { ProviderInterface } from '../types'; + +const mocks = require('./mocks'); +const send = require('./send'); +const state = require('./state'); +const subscribe = require('./subscribe'); +const unsubscribe = require('./unsubscribe'); + +module.exports = function mockProvider (): ProviderInterface { + const self = state(); + + mocks(self); + + return { + isConnected: (): boolean => + true, + send: (method: string, params: Array): Promise => + send(self, method, params), + subscribe: (method: string, ...params: Array): Promise => + subscribe(self, method, params), + unsubscribe: (id: number): Promise => + unsubscribe(self, id) + }; +}; diff --git a/packages/api-provider/src/mock/mocks.js b/packages/api-provider/src/mock/mocks.js new file mode 100644 index 0000000000..81b0295bd0 --- /dev/null +++ b/packages/api-provider/src/mock/mocks.js @@ -0,0 +1,33 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. +// @flow + +import type { MockState, MockState$Subscription$Callback } from './types'; + +module.exports = function mocks ({ subscriptions }: MockState): void { + let blockNumber = 0; + + const updateSubs = (method, value) => { + subscriptions[method].lastValue = value; + + Object + .values(subscriptions[method].callbacks) + .forEach((cb) => { + try { + // flowlint-next-line unclear-type:off + ((cb: any): MockState$Subscription$Callback)(null, value); + } catch (error) { + console.error(`Error on '${method}' subscription`, error); + } + }); + }; + + setInterval(() => { + updateSubs('extra_getBlockNumber', `0x${(++blockNumber).toString(16)}`); + }, 5000); + + setInterval(() => { + updateSubs('extra_getClientTime', `0x${Date.now().toString(16)}`); + }, 1000); +}; diff --git a/packages/api-provider/src/mock/send.js b/packages/api-provider/src/mock/send.js new file mode 100644 index 0000000000..25619b0c25 --- /dev/null +++ b/packages/api-provider/src/mock/send.js @@ -0,0 +1,10 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. +// @flow + +import type { MockState } from './types'; + +module.exports = async function send (self: MockState, method: string, params: Array): Promise { + throw new Error('provider.send not implemented'); +}; diff --git a/packages/api-provider/src/mock/state.js b/packages/api-provider/src/mock/state.js new file mode 100644 index 0000000000..aebd9525f9 --- /dev/null +++ b/packages/api-provider/src/mock/state.js @@ -0,0 +1,35 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. +// @flow + +import type { MockState } from './types'; + +const interfaces = require('@polkadot/api-jsonrpc'); +const l = require('@polkadot/util/logger')('api-mock'); + +const METHODS = Array.prototype.concat.apply( + [], Object.keys(interfaces).map((section) => { + return Object + .keys(interfaces[section].methods) + .map((method) => `${section}_${method}`); + }) +); + +module.exports = function state (): MockState { + const subscriptions = METHODS.reduce((subscriptions, name) => { + subscriptions[name] = { + callbacks: {}, + lastValue: null + }; + + return subscriptions; + }, {}); + + return { + l, + subscriptionId: 0, + subscriptionMap: {}, + subscriptions + }; +}; diff --git a/packages/api-provider/src/mock/state.spec.js b/packages/api-provider/src/mock/state.spec.js new file mode 100644 index 0000000000..e628639c7b --- /dev/null +++ b/packages/api-provider/src/mock/state.spec.js @@ -0,0 +1,33 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. + +const createState = require('./state'); + +describe('state', () => { + let state; + + beforeEach(() => { + state = createState(); + }); + + it('generates a sane initial state', () => { + expect( + state + ).toMatchObject({ + subscriptionId: 0, + subscriptionMap: {} + }); + }); + + it('generates a proper section_method map', () => { + expect( + state.subscriptions + ).toMatchObject({ + 'extra_getBlockNumber': { + callbacks: {}, + lastValue: null + } + }); + }); +}); diff --git a/packages/api-provider/src/mock/subscribe.js b/packages/api-provider/src/mock/subscribe.js new file mode 100644 index 0000000000..4e38e774b2 --- /dev/null +++ b/packages/api-provider/src/mock/subscribe.js @@ -0,0 +1,25 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. +// @flow + +import type { MockState, MockState$Subscription$Callback } from './types'; + +module.exports = async function subscribe (self: MockState, method: string, params: Array): Promise { + self.l.debug(() => ['subscribe', method, params]); + + if (self.subscriptions[method]) { + // flowlint-next-line unclear-type:off + const callback = ((params.pop(): any): MockState$Subscription$Callback); + const id = ++self.subscriptionId; + + self.subscriptions[method].callbacks[id] = callback; + self.subscriptionMap[id] = method; + + callback(null, self.subscriptions[method].lastValue); + + return id; + } + + throw new Error(`provider.subscribe: Invalid method '${method}'`); +}; diff --git a/packages/api-provider/src/mock/subscribe.spec.js b/packages/api-provider/src/mock/subscribe.spec.js new file mode 100644 index 0000000000..c42d2b77c1 --- /dev/null +++ b/packages/api-provider/src/mock/subscribe.spec.js @@ -0,0 +1,44 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. + +const createState = require('./state'); +const subscribe = require('./subscribe'); + +describe('subscribe', () => { + let state; + + beforeEach(() => { + state = createState(); + }); + + it('fails on unknown methods', () => { + return subscribe(state, 'test_notFound').catch((error) => { + expect(error.message).toMatch(/Invalid method 'test_notFound'/); + }); + }); + + it('returns a subscription id', () => { + return subscribe(state, 'extra_getBlockNumber', [() => void 0]).then((id) => { + expect(id).toEqual(state.subscriptionId); + }); + }); + + it('stores the mapping values', () => { + const cb = () => void 0; + + return subscribe(state, 'extra_getBlockNumber', [cb]).then((id) => { + expect(state.subscriptionMap[id]).toEqual('extra_getBlockNumber'); + expect(state.subscriptions['extra_getBlockNumber'].callbacks[id]).toEqual(cb); + }); + }); + + it('calls back with the last known value', (done) => { + state.subscriptions['extra_getBlockNumber'].lastValue = 'testValue'; + + subscribe(state, 'extra_getBlockNumber', [(_, value) => { + expect(value).toEqual('testValue'); + done(); + }]); + }); +}); diff --git a/packages/api-provider/src/mock/types.js b/packages/api-provider/src/mock/types.js new file mode 100644 index 0000000000..6462c54ec4 --- /dev/null +++ b/packages/api-provider/src/mock/types.js @@ -0,0 +1,26 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. +// @flow + +import type { Logger } from '@polkadot/util/types'; + +export type MockState$Subscription$Callback = (error: ?Error, value: mixed) => void; + +export type MockState$Subscriptions = { + [string]: { + callbacks: { + [number]: MockState$Subscription$Callback + }, + lastValue: mixed + } +}; + +export type MockState = { + l: Logger, + subscriptionId: number, + subscriptionMap: { + [number]: string + }, + subscriptions: MockState$Subscriptions +}; diff --git a/packages/api-provider/src/mock/unsubscribe.js b/packages/api-provider/src/mock/unsubscribe.js new file mode 100644 index 0000000000..2aab2a5a83 --- /dev/null +++ b/packages/api-provider/src/mock/unsubscribe.js @@ -0,0 +1,21 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. +// @flow + +import type { MockState } from './types'; + +module.exports = async function subscribe (self: MockState, id: number): Promise { + const method = self.subscriptionMap[id]; + + self.l.debug(() => ['unsubscribe', id, method]); + + if (!method) { + throw new Error(`Unable to find subscription for ${id}`); + } + + delete self.subscriptionMap[id]; + delete self.subscriptions[method].callbacks[id]; + + return true; +}; diff --git a/packages/api-provider/src/mock/unsubscribe.spec.js b/packages/api-provider/src/mock/unsubscribe.spec.js new file mode 100644 index 0000000000..84f4d879c7 --- /dev/null +++ b/packages/api-provider/src/mock/unsubscribe.spec.js @@ -0,0 +1,45 @@ +// Copyright 2017-2018 Jaco Greeff +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. + +const createState = require('./state'); +const subscribe = require('./subscribe'); +const unsubscribe = require('./unsubscribe'); + +describe('unsubscribe', () => { + let state; + let id; + + beforeEach(() => { + state = createState(); + + return subscribe(state, 'extra_getBlockNumber', [() => void 0]).then((_id) => { + id = _id; + }); + }); + + it('fails on unknown ids', () => { + return unsubscribe(state, 5).catch((error) => { + expect(error.message).toMatch(/Unable to find/); + }); + }); + + it('unsubscribes successfully', () => { + return unsubscribe(state, id); + }); + + it('fails on double unsubscribe', () => { + return unsubscribe(state, id) + .then(() => unsubscribe(state, id)) + .catch((error) => { + expect(error.message).toMatch(/Unable to find/); + }); + }); + + it('clears the subscriptions', () => { + return unsubscribe(state, id).then(() => { + expect(state.subscriptionMap[id]).not.toBeDefined(); + expect(state.subscriptions['extra_getBlockNumber'].callbacks[id]).not.toBeDefined(); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 327325a155..d813cf6d05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -79,9 +79,9 @@ lodash "^4.2.0" to-fast-properties "^2.0.0" -"@polkadot/dev@^0.16.17": - version "0.16.17" - resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.16.17.tgz#530653a5659a9d6a0784aeed99b219ee3a56d340" +"@polkadot/dev@^0.16.19": + version "0.16.19" + resolved "https://registry.yarnpkg.com/@polkadot/dev/-/dev-0.16.19.tgz#9d3158c43bd75688428e264e47937b838a0560af" dependencies: babel-cli "^6.26.0" babel-core "^6.26.0" @@ -91,6 +91,7 @@ babel-plugin-transform-object-rest-spread "^6.26.0" babel-plugin-transform-runtime "^6.23.0" babel-preset-env "^1.6.1" + codeclimate-test-reporter "^0.5.0" coveralls "^3.0.0" dox "^0.9.0" eslint "^4.18.2" @@ -105,7 +106,7 @@ eslint-plugin-promise "^3.6.0" eslint-plugin-react "^7.7.0" eslint-plugin-standard "^3.0.1" - flow-bin "^0.67.1" + flow-bin "^0.68.0" flow-copy-source "^1.3.0" jest "^22.4.2" makeshift "^1.1.0" @@ -441,7 +442,7 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" -async@^1.4.0, async@^1.5.0: +async@^1.4.0, async@^1.5.0, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -1258,6 +1259,10 @@ capture-stack-trace@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -1281,7 +1286,7 @@ center-align@^0.1.1: deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@^1.1.3: +chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -1437,6 +1442,15 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" +codeclimate-test-reporter@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/codeclimate-test-reporter/-/codeclimate-test-reporter-0.5.0.tgz#93fa06b1c18e4117349128dc4e38aad08043828e" + dependencies: + async "~1.5.2" + commander "2.9.0" + lcov-parse "0.0.10" + request "~2.79.0" + collapse-white-space@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.3.tgz#4b906f670e5a963a87b76b0e1689643341b6023c" @@ -1475,16 +1489,20 @@ command-join@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/command-join/-/command-join-2.0.0.tgz#52e8b984f4872d952ff1bdc8b98397d27c7144cf" -commander@^2.11.0: - version "2.12.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" - -commander@~2.9.0: +commander@2.9.0, commander@~2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" dependencies: graceful-readlink ">= 1.0.0" +commander@^2.11.0: + version "2.12.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" + +commander@^2.9.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322" + compare-func@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" @@ -2444,9 +2462,9 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -flow-bin@^0.67.1: - version "0.67.1" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.67.1.tgz#eabb7197cce870ac9442cfd04251c7ddc30377db" +flow-bin@^0.68.0: + version "0.68.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.68.0.tgz#86c2d14857d306eb2e85e274f2eebf543564f623" flow-copy-source@^1.3.0: version "1.3.0" @@ -2567,6 +2585,16 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" @@ -2768,6 +2796,15 @@ har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + har-validator@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" @@ -3159,6 +3196,20 @@ is-hexadecimal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + +is-my-json-valid@^2.12.4: + version "2.17.2" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -3223,6 +3274,10 @@ is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -3754,6 +3809,10 @@ jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -3815,7 +3874,7 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" -lcov-parse@^0.0.10: +lcov-parse@0.0.10, lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" @@ -4811,6 +4870,10 @@ qs@^6.5.1, qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +qs@~6.3.0: + version "6.3.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" + qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -5128,6 +5191,31 @@ request@^2.79.0, request@^2.83.0: tunnel-agent "^0.6.0" uuid "^3.1.0" +request@~2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -5853,6 +5941,10 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -6215,7 +6307,7 @@ xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" -xtend@^4.0.1, xtend@~4.0.1: +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"