diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d0a1f87b..79d2b0fea0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +## [6.0.1] - 2021-02-05 + +### Changed + +- Update `typedoc` from v0.15 to v20.20 ([#333](https://github.com/MetaMask/controllers/pull/333)) +- Update `@metamask/contract-metadata` from v1.19 to v1.22 ([#332](https://github.com/MetaMask/controllers/pull/332)) +- Bump node-notifier from 8.0.0 to 8.0.1 ([#323](https://github.com/MetaMask/controllers/pull/323)) + +### Fixed + +- Add `safelyExecuteWithTimeout` for `accountTracker.refresh` ([#331](https://github.com/MetaMask/controllers/pull/331)) +- Add try/catch for `assetsContract.getBalanceOf` ([#328](https://github.com/MetaMask/controllers/pull/328)) + ## [6.0.0] - 2021-01-19 ### Changed @@ -161,7 +174,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Remove shapeshift controller (#209) -[Unreleased]:https://github.com/MetaMask/controllers/compare/v6.0.0...HEAD +[Unreleased]:https://github.com/MetaMask/controllers/compare/v6.0.1...HEAD +[6.0.1]:https://github.com/MetaMask/controllers/compare/v6.0.0...v6.0.1 [6.0.0]:https://github.com/MetaMask/controllers/compare/v5.1.0...v6.0.0 [5.1.0]:https://github.com/MetaMask/controllers/compare/v5.0.0...v5.1.0 [5.0.0]:https://github.com/MetaMask/controllers/compare/v4.2.0...v5.0.0 diff --git a/package.json b/package.json index 13a9ea9d54..0b9d2aef24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/controllers", - "version": "6.0.0", + "version": "6.0.1", "description": "Collection of platform-agnostic modules for creating secure data models for cryptocurrency wallets", "license": "MIT", "files": [ @@ -20,7 +20,7 @@ "build": "rm -rf dist && tsc", "build:watch": "yarn build && tsc -w", "build:link": "yarn build && cd dist && yarn link && rm -rf node_modules && cd ..", - "doc": "typedoc src/ && touch docs/.nojekyll" + "doc": "typedoc && touch docs/.nojekyll" }, "homepage": "https://github.com/MetaMask/controllers#readme", "repository": { @@ -35,7 +35,7 @@ "url": "https://github.com/MetaMask/controllers/issues" }, "dependencies": { - "@metamask/contract-metadata": "^1.19.0", + "@metamask/contract-metadata": "^1.22.0", "await-semaphore": "^0.1.3", "eth-ens-namehash": "^2.0.8", "eth-json-rpc-infura": "^5.1.0", @@ -47,7 +47,6 @@ "eth-sig-util": "^3.0.0", "ethereumjs-util": "^6.1.0", "ethereumjs-wallet": "^0.6.4", - "ethjs-query": "^0.3.8", "human-standard-collectible-abi": "^1.0.2", "human-standard-token-abi": "^2.0.0", "isomorphic-fetch": "^3.0.0", @@ -78,7 +77,7 @@ "prettier": "^2.1.1", "sinon": "^7.4.1", "ts-jest": "^26.3.0", - "typedoc": "^0.15.0", + "typedoc": "^0.20.20", "typescript": "^4.0.3" }, "jest": { diff --git a/src/assets/AccountTrackerController.ts b/src/assets/AccountTrackerController.ts index 2cd3734936..d378669fe6 100644 --- a/src/assets/AccountTrackerController.ts +++ b/src/assets/AccountTrackerController.ts @@ -1,8 +1,9 @@ import BaseController, { BaseConfig, BaseState } from '../BaseController'; import PreferencesController from '../user/PreferencesController'; -import { BNToHex, safelyExecute } from '../util'; +import { BNToHex, query, safelyExecuteWithTimeout } from '../util'; -const EthjsQuery = require('ethjs-query'); +const EthQuery = require('eth-query'); +const { Mutex } = require('await-semaphore'); /** * @type AccountInformation @@ -42,7 +43,9 @@ export interface AccountTrackerState extends BaseState { * Controller that tracks information for all accounts in the current keychain */ export class AccountTrackerController extends BaseController { - private ethjsQuery: any; + private ethQuery: any; + + private mutex = new Mutex(); private handle?: NodeJS.Timer; @@ -95,7 +98,7 @@ export class AccountTrackerController extends BaseController { + const releaseLock = await this.mutex.acquire(); interval && this.configure({ interval }, false, false); this.handle && clearTimeout(this.handle); - await safelyExecute(() => this.refresh()); + await this.refresh(); this.handle = setTimeout(() => { + releaseLock(); this.poll(this.config.interval); }, this.config.interval); } @@ -130,8 +135,8 @@ export class AccountTrackerController extends BaseController { - const balance = await this.ethjsQuery.getBalance(address); + await safelyExecuteWithTimeout(async () => { + const balance = await query(this.ethQuery, 'getBalance', [address]); accounts[address] = { balance: BNToHex(balance) }; this.update({ accounts: { ...accounts } }); }); diff --git a/src/assets/TokenBalancesController.ts b/src/assets/TokenBalancesController.ts index 4ea132ddbd..f951ffac3e 100644 --- a/src/assets/TokenBalancesController.ts +++ b/src/assets/TokenBalancesController.ts @@ -96,7 +96,13 @@ export class TokenBalancesController extends BaseController { - return new Promise((resolve, reject) => { - this.ethQuery[method](...args, (error: Error, result: any) => { - if (error) { - reject(error); - return; - } - resolve(result); - }); - }); - } - private async registryLookup(fourBytePrefix: string): Promise { const registryMethod = await this.registry.lookup(fourBytePrefix); const parsedRegistryMethod = this.registry.parse(registryMethod); @@ -490,7 +479,7 @@ export class TransactionController extends BaseController { if (meta.status === 'submitted' && meta.networkID === currentNetworkID) { - const txObj = await this.query('getTransactionByHash', [meta.transactionHash]); + const txObj = await query(this.ethQuery, 'getTransactionByHash', [meta.transactionHash]); /* istanbul ignore else */ if (txObj && txObj.blockNumber) { transactions[index].status = 'confirmed'; @@ -806,7 +795,7 @@ export class TransactionController extends BaseController Promise, logError = fa } } +/** + * Execute and return an asynchronous operation with a timeout + * + * @param operation - Function returning a Promise + * @param logError - Determines if the error should be logged + * @param retry - Function called if an error is caught + * @param timeout - Timeout to fail the operation + * @returns - Promise resolving to the result of the async operation + */ +export async function safelyExecuteWithTimeout(operation: () => Promise, logError = false, timeout = 500) { + try { + return await Promise.race([ + operation(), + new Promise((_, reject) => + setTimeout(() => { + reject(new Error('timeout')); + }, timeout), + ), + ]); + } catch (error) { + /* istanbul ignore next */ + if (logError) { + console.error(error); + } + } +} + /** * Validates a Transaction object for required properties and throws in * the event of any validation error. @@ -445,9 +472,31 @@ export function normalizeEnsName(ensName: string): string | null { return null; } +/** + * Wrapper method to handle EthQuery requests + * + * @param ethQuery - EthQuery object initialized with a provider + * @param method - Method to request + * @param args - Arguments to send + * + * @returns - Promise resolving the request + */ +export function query(ethQuery: any, method: string, args: any[] = []): Promise { + return new Promise((resolve, reject) => { + ethQuery[method](...args, (error: Error, result: any) => { + if (error) { + reject(error); + return; + } + resolve(result); + }); + }); +} + export default { BNToHex, fractionBN, + query, getBuyURL, handleFetch, hexToBN, @@ -455,6 +504,7 @@ export default { isSmartContractCode, normalizeTransaction, safelyExecute, + safelyExecuteWithTimeout, successfulFetch, timeoutFetch, validateTokenToWatch, diff --git a/tests/TokenBalancesController.test.ts b/tests/TokenBalancesController.test.ts index 9ffd7764f0..e92209a4a1 100644 --- a/tests/TokenBalancesController.test.ts +++ b/tests/TokenBalancesController.test.ts @@ -16,6 +16,11 @@ describe('TokenBalancesController', () => { let tokenBalances: TokenBalancesController; const sandbox = createSandbox(); + const getToken = (address: string) => { + const { tokens } = tokenBalances.config; + return tokens.find((token) => token.address === address); + }; + beforeEach(() => { tokenBalances = new TokenBalancesController(); }); @@ -85,6 +90,36 @@ describe('TokenBalancesController', () => { assetsContract.configure({ provider: MAINNET_PROVIDER }); stub(assetsContract, 'getBalanceOf').returns(new BN(1)); await tokenBalances.updateBalances(); + const mytoken = getToken(address); + expect(mytoken?.balanceError).toBeNull(); + expect(Object.keys(tokenBalances.state.contractBalances)).toContain(address); + expect(tokenBalances.state.contractBalances[address].toNumber()).toBeGreaterThan(0); + }); + + it('should handle `getBalanceOf` error case', async () => { + const errorMsg = 'Failed to get balance'; + const address = '0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0'; + expect(tokenBalances.state.contractBalances).toEqual({}); + tokenBalances.configure({ tokens: [{ address, decimals: 18, symbol: 'EOS' }] }); + const assets = new AssetsController(); + const assetsContract = new AssetsContractController(); + const network = new NetworkController(); + const preferences = new PreferencesController(); + + new ComposableController([assets, assetsContract, network, preferences, tokenBalances]); + assetsContract.configure({ provider: MAINNET_PROVIDER }); + const mock = stub(assetsContract, 'getBalanceOf').returns(Promise.reject(new Error(errorMsg))); + await tokenBalances.updateBalances(); + const mytoken = getToken(address); + expect(mytoken?.balanceError).toBeInstanceOf(Error); + expect(mytoken?.balanceError?.message).toBe(errorMsg); + expect(tokenBalances.state.contractBalances[address]).toEqual(0); + + // test reset case + mock.restore(); + stub(assetsContract, 'getBalanceOf').returns(new BN(1)); + await tokenBalances.updateBalances(); + expect(mytoken?.balanceError).toBeNull(); expect(Object.keys(tokenBalances.state.contractBalances)).toContain(address); expect(tokenBalances.state.contractBalances[address].toNumber()).toBeGreaterThan(0); }); diff --git a/tests/util.test.ts b/tests/util.test.ts index dfcc20d309..12a27e6df1 100644 --- a/tests/util.test.ts +++ b/tests/util.test.ts @@ -7,6 +7,46 @@ const { BN } = require('ethereumjs-util'); const SOME_API = 'https://someapi.com'; const SOME_FAILING_API = 'https://somefailingapi.com'; +const HttpProvider = require('ethjs-provider-http'); +const EthQuery = require('eth-query'); + +const mockFlags: { [key: string]: any } = { + estimateGas: null, + gasPrice: null, +}; +const PROVIDER = new HttpProvider('https://ropsten.infura.io/v3/341eacb578dd44a1a049cbc5f6fd4035'); + +jest.mock('eth-query', () => + jest.fn().mockImplementation(() => { + return { + estimateGas: (_transaction: any, callback: any) => { + callback(undefined, '0x0'); + }, + gasPrice: (callback: any) => { + if (mockFlags.gasPrice) { + callback(new Error(mockFlags.gasPrice)); + return; + } + callback(undefined, '0x0'); + }, + getBlockByNumber: (_blocknumber: any, _fetchTxs: boolean, callback: any) => { + callback(undefined, { gasLimit: '0x0' }); + }, + getCode: (_to: any, callback: any) => { + callback(undefined, '0x0'); + }, + getTransactionByHash: (_hash: any, callback: any) => { + callback(undefined, { blockNumber: '0x1' }); + }, + getTransactionCount: (_from: any, _to: any, callback: any) => { + callback(undefined, '0x0'); + }, + sendRawTransaction: (_transaction: any, callback: any) => { + callback(undefined, '1337'); + }, + }; + }), +); describe('util', () => { beforeEach(() => { @@ -79,6 +119,31 @@ describe('util', () => { }); }); + describe('safelyExecuteWithTimeout', () => { + it('should swallow errors', async () => { + await util.safelyExecuteWithTimeout(() => { + throw new Error('ahh'); + }); + }); + + it('should resolve', async () => { + const response = await util.safelyExecuteWithTimeout(() => { + return new Promise((res) => setTimeout(() => res('response'), 200)); + }); + expect(response).toEqual('response'); + }); + + it('should timeout', () => { + try { + util.safelyExecuteWithTimeout(() => { + return new Promise((res) => setTimeout(res, 800)); + }); + } catch (e) { + expect(e.message).toContain('timeout'); + } + }); + }); + describe('validateTransaction', () => { it('should throw if no from address', () => { expect(() => util.validateTransaction({} as any)).toThrow(); @@ -577,4 +642,22 @@ describe('util', () => { expect(invalid).toBeNull(); }); }); + + describe('query', () => { + it('should query and resolve', async () => { + const ethQuery = new EthQuery(PROVIDER); + const gasPrice = await util.query(ethQuery, 'gasPrice', []); + expect(gasPrice).toEqual('0x0'); + }); + + it('should query and reject if error', async () => { + const ethQuery = new EthQuery(PROVIDER); + mockFlags.gasPrice = 'Uh oh'; + try { + await util.query(ethQuery, 'gasPrice', []); + } catch (error) { + expect(error.message).toContain('Uh oh'); + } + }); + }); }); diff --git a/tsconfig.json b/tsconfig.json index 4acb76ae4a..fe2ce4c717 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,15 +16,6 @@ "strict": true, "target": "es6" }, - "typedocOptions": { - "exclude": "**/*.test.ts", - "excludeNotExported": true, - "excludePrivate": true, - "hideGenerator": true, - "mode": "modules", - "out": "docs", - "theme": "default" - }, "include": [ "./src/**/*.ts" ] diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000000..b527b62572 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,6 @@ +{ + "entryPoints": ["./src/index.ts"], + "excludePrivate": true, + "hideGenerator": true, + "out": "docs" +} diff --git a/yarn.lock b/yarn.lock index a9f7f88cea..bf330f6701 100644 --- a/yarn.lock +++ b/yarn.lock @@ -625,10 +625,10 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@metamask/contract-metadata@^1.19.0": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.19.0.tgz#2f074bce7ab7ffd0d20e3905b1936da0749a0473" - integrity sha512-TklMuz7ZbFJ2Zc6C7I+9qL3J9J+4prs5Ok5MJzoxD/57Iq6espzArhpI275elVCFF9ci8IMvach1kH8+F04/hA== +"@metamask/contract-metadata@^1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.22.0.tgz#55cc84756c703c433176b484b1d34f0e03d16d1e" + integrity sha512-t4ijbU+4OH9UAlrPkfLPFo6KmkRTRZJHB+Vly4ajF8oZMnota5YjVVl/SmltsoRC9xvJtRn9DUVf3YMHMIdofw== "@metamask/eslint-config@^3.0.0": version "3.2.0" @@ -806,11 +806,6 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/minimatch@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - "@types/node@*", "@types/node@^10.1.4": version "10.14.15" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.15.tgz#e8f7729b631be1b02ae130ff0b61f3e018000640" @@ -1251,6 +1246,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -1339,13 +1339,6 @@ babel-runtime@^6.26.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -backbone@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.4.0.tgz#54db4de9df7c3811c3f032f34749a4cd27f3bd12" - integrity sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ== - dependencies: - underscore ">=1.8.3" - backoff@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" @@ -1776,6 +1769,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colors@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -2810,16 +2808,6 @@ ethjs-query@0.3.7: ethjs-rpc "0.2.0" promise-to-callback "^1.0.0" -ethjs-query@^0.3.8: - version "0.3.8" - resolved "https://registry.yarnpkg.com/ethjs-query/-/ethjs-query-0.3.8.tgz#aa5af02887bdd5f3c78b3256d0f22ffd5d357490" - integrity sha512-/J5JydqrOzU8O7VBOwZKUWXxHDGr46VqNjBCJgBVNNda+tv7Xc8Y2uJc6aMHHVbeN3YOQ7YRElgIc0q1CI02lQ== - dependencies: - babel-runtime "^6.26.0" - ethjs-format "0.2.7" - ethjs-rpc "0.2.0" - promise-to-callback "^1.0.0" - ethjs-rpc@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ethjs-rpc/-/ethjs-rpc-0.2.0.tgz#3d0011e32cfff156ed6147818c6fb8f801701b4c" @@ -3203,14 +3191,15 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== dependencies: + at-least-node "^1.0.0" graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^6.0.1" + universalify "^2.0.0" fs.realpath@^1.0.0: version "1.0.0" @@ -3361,7 +3350,7 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -handlebars@^4.1.2: +handlebars@^4.7.6: version "4.7.6" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== @@ -3467,11 +3456,6 @@ hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: inherits "^2.0.3" minimalistic-assert "^1.0.1" -highlight.js@^9.15.8: - version "9.18.5" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" - integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== - hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4436,11 +4420,6 @@ jest@^26.4.2: import-local "^3.0.2" jest-cli "^26.4.2" -jquery@^3.4.1: - version "3.5.0" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.0.tgz#9980b97d9e4194611c36530e7dc46a58d7340fc9" - integrity sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ== - js-sha3@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.5.tgz#baf0c0e8c54ad5903447df96ade7a4a1bca79a4a" @@ -4607,10 +4586,12 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" @@ -4888,7 +4869,7 @@ lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== -lodash@^4.17.19: +lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -4940,15 +4921,29 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= -lunr@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.6.tgz#f278beee7ffd56ad86e6e478ce02ab2b98c78dd5" - integrity sha512-swStvEyDqQ85MGpABCMBclZcLI/pBIlu8FFDtmX197+oEgKloJ67QnB+Tidh0340HmLMs39c4GrkPY3cmkXp6Q== +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== make-dir@^3.0.0: version "3.0.2" @@ -4981,10 +4976,10 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -marked@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" - integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== +marked@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.8.tgz#5008ece15cfa43e653e85845f3525af4beb6bdd4" + integrity sha512-lzmFjGnzWHkmbk85q/ILZjFoHHJIQGF+SxGEfIdGk/XhiTPhqGs37gbru6Kkd48diJnEyYwnG67nru0Z2gQtuQ== md5.js@^1.3.4: version "1.3.5" @@ -5228,9 +5223,9 @@ node-modules-regexp@^1.0.0: integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= node-notifier@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.0.tgz#a7eee2d51da6d0f7ff5094bc7108c911240c1620" - integrity sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA== + version "8.0.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.1.tgz#f86e89bbc925f2b068784b31f382afdc6ca56be1" + integrity sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA== dependencies: growly "^1.3.0" is-wsl "^2.2.0" @@ -5406,6 +5401,13 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +onigasm@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/onigasm/-/onigasm-2.2.5.tgz#cc4d2a79a0fa0b64caec1f4c7ea367585a676892" + integrity sha512-F+th54mPc0l1lp1ZcFMyL/jTs2Tlq4SqIHKIXGZOR/VkHkF9A7Fr5rRr5+ZG/lWeRsyrClLYRq7s/yFQ/XhWCA== + dependencies: + lru-cache "^5.1.1" + optionator@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" @@ -6268,9 +6270,11 @@ semaphore@>=1.0.1, semaphore@^1.0.3: integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@7.x, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: version "6.3.0" @@ -6346,10 +6350,10 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" - integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== +shelljs@^0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" + integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -6360,6 +6364,31 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== +shiki-languages@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/shiki-languages/-/shiki-languages-0.2.7.tgz#7230b675b96d37a36ac1bf995525375ce69f3924" + integrity sha512-REmakh7pn2jCn9GDMRSK36oDgqhh+rSvJPo77sdWTOmk44C5b0XlYPwJZcFOMJWUZJE0c7FCbKclw4FLwUKLRw== + dependencies: + vscode-textmate "^5.2.0" + +shiki-themes@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/shiki-themes/-/shiki-themes-0.2.7.tgz#6e04451d832152e0fc969876a7bd926b3963c1f2" + integrity sha512-ZMmboDYw5+SEpugM8KGUq3tkZ0vXg+k60XX6NngDK7gc1Sv6YLUlanpvG3evm57uKJvfXsky/S5MzSOTtYKLjA== + dependencies: + json5 "^2.1.0" + vscode-textmate "^5.2.0" + +shiki@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.2.7.tgz#d2547548ed8742673730e1e4bbe792a77c445540" + integrity sha512-bwVc7cdtYYHEO9O+XJ8aNOskKRfaQd5Y4ovLRfbQkmiLSUaR+bdlssbZUUhbQ0JAFMYcTcJ5tjG5KtnufttDHQ== + dependencies: + onigasm "^2.2.5" + shiki-languages "^0.2.7" + shiki-themes "^0.2.7" + vscode-textmate "^5.2.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -6985,37 +7014,27 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedoc-default-themes@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.6.0.tgz#7e73bf54dd9e11550dd0fb576d5176b758f8f8b5" - integrity sha512-MdTROOojxod78CEv22rIA69o7crMPLnVZPefuDLt/WepXqJwgiSu8Xxq+H36x0Jj3YGc7lOglI2vPJ2GhoOybw== - dependencies: - backbone "^1.4.0" - jquery "^3.4.1" - lunr "^2.3.6" - underscore "^1.9.1" - -typedoc@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.15.0.tgz#21eaf4db41cf2797bad027a74f2a75cd08ae0c2d" - integrity sha512-NOtfq5Tis4EFt+J2ozhVq9RCeUnfEYMFKoU6nCXCXUULJz1UQynOM+yH3TkfZCPLzigbqB0tQYGVlktUWweKlw== - dependencies: - "@types/minimatch" "3.0.3" - fs-extra "^8.1.0" - handlebars "^4.1.2" - highlight.js "^9.15.8" - lodash "^4.17.15" - marked "^0.7.0" +typedoc-default-themes@^0.12.7: + version "0.12.7" + resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.12.7.tgz#d44f68d40a3e90a19b5ea7be4cc6ed949afe768d" + integrity sha512-0XAuGEqID+gon1+fhi4LycOEFM+5Mvm2PjwaiVZNAzU7pn3G2DEpsoXnFOPlLDnHY6ZW0BY0nO7ur9fHOFkBLQ== + +typedoc@^0.20.20: + version "0.20.20" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.20.20.tgz#0f0915fb73e7371fc2cf8c74b6a3207dcf5c3dda" + integrity sha512-qXB40ttDGaqv6q6UIiAVqOpX/GlXoBur0lB4g9fePoYjfwa6OsPkoYufLtsjEaBB0EokShR2aIoI5GX4RB83cw== + dependencies: + colors "^1.4.0" + fs-extra "^9.1.0" + handlebars "^4.7.6" + lodash "^4.17.20" + lunr "^2.3.9" + marked "^1.2.8" minimatch "^3.0.0" progress "^2.0.3" - shelljs "^0.8.3" - typedoc-default-themes "^0.6.0" - typescript "3.5.x" - -typescript@3.5.x: - version "3.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" - integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== + shelljs "^0.8.4" + shiki "^0.2.7" + typedoc-default-themes "^0.12.7" typescript@^4.0.3: version "4.0.3" @@ -7030,11 +7049,6 @@ uglify-js@^3.1.4: commander "~2.20.3" source-map "~0.6.1" -underscore@>=1.8.3, underscore@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -7045,10 +7059,10 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== unorm@^1.3.3: version "1.6.0" @@ -7101,9 +7115,9 @@ uuid@^3.3.2: integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== uuid@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" - integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@^2.0.3: version "2.1.1" @@ -7136,6 +7150,11 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vscode-textmate@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" + integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== + w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -7400,6 +7419,16 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@18.x, yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"