diff --git a/.eslintignore b/.eslintignore index 0db7c2a8..ed812816 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,3 @@ examples/ -types/sosuisen__nodegit/ dist/ +*.mjs \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 1af7bad3..f777576b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -31,6 +31,7 @@ }, "rules": { + "import/no-named-as-default-member": "off", "unicorn/no-unreadable-array-destructuring": "off", "no-restricted-syntax": [ "error", diff --git a/.npmignore b/.npmignore index 9f3284e7..21828505 100644 --- a/.npmignore +++ b/.npmignore @@ -33,10 +33,13 @@ node_modules/ # test coverage/ test/ -test_intg/ +test_plugin/ dist/test/ .nyc_output/ # api-extractor temp/ etc/ + +# script +remove_remote_repositories.mjs diff --git a/.vscode/launch.json b/.vscode/launch.json index 06a25ddd..acd1bdec 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,7 +4,7 @@ "type": "pickString", "id": "choice", "description": "select a file", - "options": ["test/collection.test.js"], + "options": ["test/remote_isomorphic_git/sync_trysync.test.js"], }], "configurations": [ { diff --git a/.vscode/settings.json b/.vscode/settings.json index f40e2b6f..1f83d012 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { "editor.tabSize": 2, - "editor.detectIndentation": false + "editor.detectIndentation": false, + "cSpell.words": [ + "unicount" + ] } \ No newline at end of file diff --git a/README.md b/README.md index 1ae93d7d..7f971c19 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,23 @@ [![License: MPL 2.0](https://img.shields.io/github/license/sosuisen/git-documentdb)](LICENSE) [![Coverage Status](https://img.shields.io/coveralls/github/sosuisen/git-documentdb)](https://coveralls.io/github/sosuisen/git-documentdb?branch=main) -Offline-first DocumentDB that Syncs with Git +TypeScript Ready Offline-first Database that Syncs with Git Use GitDocumentDB to ... -:green_book: Store JSON documents into Git repository. +:nut_and_bolt: Develop offline-capable applications using Git. -:art: Manage Git repository by document database API. +:green_book: Manage JSON documents in Git repository by CRUD and collection APIs. -:rocket: Synchronize, diff and patch automatically with a remote repository. +:rocket: Synchronize automatically with remote repositories. -     (No need to resolve conflicts manually.) +     *(No need to resolve conflicts manually!)* -:arrows_counterclockwise: CI/CD through GitHub. +:arrows_counterclockwise: Integrate CI/CD pipelines through GitHub. -:dromedary_camel: Travel revisions. +:dromedary_camel: Get the revision history of a document. -You do not need knowledge of Git to start. However, you make the most of GitDocumentDB if you understand Git. +[(More...)](https://gitddb.com/) # API https://gitddb.com/docs/api/git-documentdb.gitdocumentdb @@ -29,25 +29,11 @@ https://gitddb.com/docs/api/git-documentdb.gitdocumentdb # Usage ## Getting started ### **Prerequisite** -Node.js 12 or later +Node.js v12 - v16 ### **Installation** ``` npm i git-documentdb ``` -**NOTE:**
-GitDocumentDB uses native addon (libgit2).
-If you receive errors about installation, you probably miss building tools and libraries.
-**In Ubuntu 18:**
-``` -sudo apt update -sudo apt install build-essential libssl-dev libkrb5-dev libc++-dev -``` -**In Windows 10:**
-The list below shows typical environments. -- Node.js 12, Python 2.7.x, and Visual Studio 2017 Community (with Desktop development with C++). -- npm config set msvs_version 2017 - -If you are still encountering install problems, documents about [NodeGit](https://github.com/nodegit/nodegit#getting-started) and [Building NodeGit from source](https://www.nodegit.org/guides/install/from-source/) may also help you. ## Import ```typescript @@ -239,23 +225,23 @@ https://github.com/sosuisen/inventory-manager - Automated conflict resolution :feet: - Automated JSON diff and patch :feet: - Automated combining of inconsistent repositories :feet: -- v0.4 Work on both Node.js and browser +- v0.4 Many data types and connection methods - API renewal to manage any data types :feet: - - Remove native module (NodeGit) from default install :dog2:(Next) - - Connect with SSH key pair + - Remove native module (NodeGit) from default install :feet: + - Add plugin system for remote connection (isomorphic-git or NodeGit) :feet: + - Connect with SSH key pair :feet: + - Add Front-Matter-Markdown format :feet: +- v0.5 Search + - Indexed Search :dog2:(Next) +- Until v1.0 - Connect to GitHub with OAuth - Work on browser - -- Until v1.0 - Sync any data types - Replication - - Grep - Transaction (bulk) - - Tag - - Indexed Search + - GitLab and Bitbucket - Push server - Migration - - Plugins (https://github.com/sosuisen/git-documentdb/projects/2) diff --git a/benchmark/get.ts b/benchmark/get.ts new file mode 100644 index 00000000..66f6db89 --- /dev/null +++ b/benchmark/get.ts @@ -0,0 +1,79 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import { monotonicFactory } from 'ulid'; +import { GitDocumentDB } from '../src/git_documentdb'; + +const localDir = './benchmark/database_get'; + +const ulid = monotonicFactory(); +const monoId = () => { + return ulid(Date.now()); +}; + +// eslint-disable-next-line complexity +async function bench () { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + + for (let i = 0; i < 200; i++) { + // eslint-disable-next-line no-await-in-loop + await gitDDB.put(`${i}`, { name: 'foo' }); + } + + for (let i = 0; i < 200; i++) { + // eslint-disable-next-line no-await-in-loop + await gitDDB.put(`large-${i}`, { + name: + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', + }); + } + + console.time('Load by API'); + for (let i = 0; i < 100; i++) { + // eslint-disable-next-line no-await-in-loop + const json = await gitDDB.get(`${i}`); + if (json!._id !== `${i}`) console.error('Error'); + } + console.timeEnd('Load by API'); + + console.time('Load from file'); + for (let i = 100; i < 200; i++) { + const json = fs.readJSONSync(`${gitDDB.workingDir}/${i}.json`); + if (json._id !== `${i}`) console.error('Error'); + } + console.timeEnd('Load from file'); + + console.time('Load large file by API'); + for (let i = 0; i < 100; i++) { + // eslint-disable-next-line no-await-in-loop + const json = await gitDDB.get(`large-${i}`); + if (json!._id !== `large-${i}`) console.error('Error'); + } + console.timeEnd('Load large file by API'); + + console.time('Load large file from file'); + for (let i = 100; i < 200; i++) { + const json = fs.readJSONSync(`${gitDDB.workingDir}/large-${i}.json`); + if (json._id !== `large-${i}`) console.error('Error'); + } + console.timeEnd('Load large file from file'); + + await gitDDB.destroy(); + + fs.removeSync(path.resolve(localDir)); +} + +bench(); diff --git a/benchmark/push.ts b/benchmark/push.ts new file mode 100644 index 00000000..953d92ac --- /dev/null +++ b/benchmark/push.ts @@ -0,0 +1,136 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import { monotonicFactory } from 'ulid'; +import { ConnectionSettingsGitHub, RemoteOptions } from '../src/types'; +import { GitDocumentDB } from '../src/git_documentdb'; +import { removeRemoteRepositories } from '../test/remote_utils'; +import { Sync } from '../src/remote/sync'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + +const DATA_SIZE = 1000; + +const reposPrefix = 'benchmark_push___'; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const ulid = monotonicFactory(); +const monoId = () => { + return ulid(Date.now()); +}; + +const putData = async (gitDDB: GitDocumentDB) => { + for (let i = 0; i < DATA_SIZE / 2; i++) { + // eslint-disable-next-line no-await-in-loop + await gitDDB.put(`${i}`, { name: 'foo' }); + } + // Update them + for (let i = 0; i < DATA_SIZE / 2; i++) { + // eslint-disable-next-line no-await-in-loop + await gitDDB.put(`${i}`, { name: 'foo bar' }); + } +}; + +const putLargeData = async (gitDDB: GitDocumentDB) => { + for (let i = 0; i < DATA_SIZE / 2; i++) { + // eslint-disable-next-line no-await-in-loop + await gitDDB.put(`large-${i}`, { + name: + '0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', + }); + } + // Update them + for (let i = 0; i < DATA_SIZE / 2; i++) { + // eslint-disable-next-line no-await-in-loop + await gitDDB.put(`large-${i}`, { + name: + '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', + }); + } +}; + +// eslint-disable-next-line complexity +async function bench () { + console.log('# DATA_SIZE = ' + DATA_SIZE); + + await removeRemoteRepositories(reposPrefix); + + const isomorphicLocalDir = './benchmark/database_push_isomorphic'; + + const isomorphicDbName = monoId(); + const isomorphicGitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: isomorphicDbName, + localDir: isomorphicLocalDir, + }); + await isomorphicGitDDB.open(); + const isomorphicConnection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + }; + const isomorphicOptions: RemoteOptions = { + remoteUrl: remoteURLBase + reposPrefix + 'isomorphic', + connection: isomorphicConnection, + }; + const isomorphicSync = await isomorphicGitDDB.sync(isomorphicOptions); + + await putData(isomorphicGitDDB); + console.time('Push data by isomorphic git'); + await isomorphicSync.tryPush(); + console.timeEnd('Push data by isomorphic git'); + + await putLargeData(isomorphicGitDDB); + console.time('Push large data by isomorphic git'); + await isomorphicSync.tryPush(); + console.timeEnd('Push large data by isomorphic git'); + + await isomorphicGitDDB.destroy(); + fs.removeSync(path.resolve(isomorphicLocalDir)); + + const nodegitLocalDir = './benchmark/database_push_nodegit'; + + const nodegitDbName = monoId(); + const nodegitGitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: nodegitDbName, + localDir: nodegitLocalDir, + }); + await nodegitGitDDB.open(); + const nodegitConnection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', + }; + const nodegitOptions: RemoteOptions = { + remoteUrl: remoteURLBase + reposPrefix + 'nodegit', + connection: nodegitConnection, + }; + const nodegitSync = await nodegitGitDDB.sync(nodegitOptions); + + await putData(nodegitGitDDB); + console.time('Push data by nodegit git'); + await nodegitSync.tryPush(); + console.timeEnd('Push data by nodegit git'); + + await putLargeData(nodegitGitDDB); + console.time('Push large data by nodegit git'); + await nodegitSync.tryPush(); + console.timeEnd('Push large data by nodegit git'); + + await nodegitGitDDB.destroy(); + fs.removeSync(path.resolve(nodegitLocalDir)); +} + +bench(); diff --git a/test_intg/tsconfig.json b/benchmark/tsconfig.json similarity index 100% rename from test_intg/tsconfig.json rename to benchmark/tsconfig.json diff --git a/docs-api/git-documentdb.collection.delete.md b/docs-api/git-documentdb.collection.delete.md index d559ff75..f84c16d6 100644 --- a/docs-api/git-documentdb.collection.delete.md +++ b/docs-api/git-documentdb.collection.delete.md @@ -31,15 +31,15 @@ Promise<[DeleteResultJsonDoc](./git-documentdb.deleteresultjsondoc.md) > [Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (from deleteImpl) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from deleteImpl) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (from deleteWorker) +\# Errors from deleteWorker -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (from deleteWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) (from deleteWorker) +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) -[Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) (from deleteWorker) +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) diff --git a/docs-api/git-documentdb.collection.delete_1.md b/docs-api/git-documentdb.collection.delete_1.md index 928db32e..37a99950 100644 --- a/docs-api/git-documentdb.collection.delete_1.md +++ b/docs-api/git-documentdb.collection.delete_1.md @@ -20,7 +20,7 @@ delete(jsonDoc: JsonDoc, options?: DeleteOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. Only the \_id property is referenced. shortId is a file path whose collectionPath and .json extension are omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. Only the \_id property is referenced. shortId is a file path whose collectionPath and extension are omitted. | | options | [DeleteOptions](./git-documentdb.deleteoptions.md) | | Returns: @@ -31,15 +31,15 @@ Promise<[DeleteResultJsonDoc](./git-documentdb.deleteresultjsondoc.md) > [Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (from deleteImpl) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from deleteImpl) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (from deleteWorker) +\# Errors from deleteWorker -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (from deleteWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) (from deleteWorker) +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) -[Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) (from deleteWorker) +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) diff --git a/docs-api/git-documentdb.collection.deletefatdoc.md b/docs-api/git-documentdb.collection.deletefatdoc.md index adeed87d..6b62605b 100644 --- a/docs-api/git-documentdb.collection.deletefatdoc.md +++ b/docs-api/git-documentdb.collection.deletefatdoc.md @@ -31,15 +31,15 @@ Promise<[DeleteResult](./git-documentdb.deleteresult.md) > [Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (from deleteImpl) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from deleteImpl) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (from deleteWorker) +\# Errors from deleteWorker -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (from deleteWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) (from deleteWorker) +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) -[Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) (from deleteWorker) +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) diff --git a/docs-api/git-documentdb.collection.find.md b/docs-api/git-documentdb.collection.find.md index 48355f29..0307f4ea 100644 --- a/docs-api/git-documentdb.collection.find.md +++ b/docs-api/git-documentdb.collection.find.md @@ -30,7 +30,5 @@ Promise<[JsonDoc](./git-documentdb.jsondoc.md) \[\]> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.findfatdoc.md b/docs-api/git-documentdb.collection.findfatdoc.md index ba8608a8..fc42edd4 100644 --- a/docs-api/git-documentdb.collection.findfatdoc.md +++ b/docs-api/git-documentdb.collection.findfatdoc.md @@ -30,7 +30,5 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \[\]> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.generateid.md b/docs-api/git-documentdb.collection.generateid.md index ba1980d8..2bcb299c 100644 --- a/docs-api/git-documentdb.collection.generateid.md +++ b/docs-api/git-documentdb.collection.generateid.md @@ -13,8 +13,15 @@ Generate new \_id as monotonic ULID Signature: ```typescript -generateId(): string; +generateId(seedTime?: number): string; ``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| seedTime | number | | + Returns: string diff --git a/docs-api/git-documentdb.collection.get.md b/docs-api/git-documentdb.collection.get.md index 68d75fba..776709d8 100644 --- a/docs-api/git-documentdb.collection.get.md +++ b/docs-api/git-documentdb.collection.get.md @@ -34,7 +34,5 @@ Promise<[JsonDoc](./git-documentdb.jsondoc.md) \| undefined> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.getcollections.md b/docs-api/git-documentdb.collection.getcollections.md index b9cb6691..aeef665d 100644 --- a/docs-api/git-documentdb.collection.getcollections.md +++ b/docs-api/git-documentdb.collection.getcollections.md @@ -28,7 +28,3 @@ Promise<[ICollection](./git-documentdb.icollection.md) \[\]> Array of Collections which does not include ''. -## Exceptions - -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - diff --git a/docs-api/git-documentdb.collection.getdocbyoid.md b/docs-api/git-documentdb.collection.getdocbyoid.md index b0207805..73b1655b 100644 --- a/docs-api/git-documentdb.collection.getdocbyoid.md +++ b/docs-api/git-documentdb.collection.getdocbyoid.md @@ -35,7 +35,5 @@ Promise<[Doc](./git-documentdb.doc.md) \| undefined> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.getfatdoc.md b/docs-api/git-documentdb.collection.getfatdoc.md index 9a8617d9..fa0294f2 100644 --- a/docs-api/git-documentdb.collection.getfatdoc.md +++ b/docs-api/git-documentdb.collection.getfatdoc.md @@ -29,7 +29,7 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \| undefined> - undefined if a specified data does not exist. -- FatJsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. +- FatJsonDoc if the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. @@ -39,7 +39,5 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \| undefined> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.getfatdochistory.md b/docs-api/git-documentdb.collection.getfatdochistory.md index a08e6c51..5a3039c1 100644 --- a/docs-api/git-documentdb.collection.getfatdochistory.md +++ b/docs-api/git-documentdb.collection.getfatdochistory.md @@ -30,7 +30,7 @@ Promise<([FatDoc](./git-documentdb.fatdoc.md) \| undefined)\[\]> Array of FatDoc or undefined. - undefined if a specified data does not exist or it is deleted. -- Array of FatJsonDoc if isJsonDocCollection is true or the file extension is '.json'. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. +- Array of FatJsonDoc if isJsonDocCollection is true or the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. - Array of FatBinaryDoc if described in .gitattribtues, otherwise array of FatTextDoc. @@ -44,7 +44,5 @@ See [GitDocumentDB.getHistory()](./git-documentdb.gitdocumentdb.gethistory.md) f [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.getfatdocoldrevision.md b/docs-api/git-documentdb.collection.getfatdocoldrevision.md index bb1d4591..d690b23e 100644 --- a/docs-api/git-documentdb.collection.getfatdocoldrevision.md +++ b/docs-api/git-documentdb.collection.getfatdocoldrevision.md @@ -33,7 +33,7 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \| undefined> - undefined if a specified data does not exist or it is deleted. -- JsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. +- JsonDoc if the file extension is SerializedFormat.extension. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. @@ -52,7 +52,5 @@ collection.getFatDocOldRevision(shortName, 2); // returns a FatDoc two revisions [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.gethistory.md b/docs-api/git-documentdb.collection.gethistory.md index 2adc901f..07990884 100644 --- a/docs-api/git-documentdb.collection.gethistory.md +++ b/docs-api/git-documentdb.collection.gethistory.md @@ -27,12 +27,14 @@ getHistory(_id: string, historyOptions?: HistoryOptions): Promise<(JsonDoc | und Promise<([JsonDoc](./git-documentdb.jsondoc.md) \| undefined)\[\]> -Array of JsonDoc or undefined. - undefined if a specified document does not exist or it is deleted. +Array of JsonDoc or undefined if a specified document does not exist or it is deleted. ## Remarks - By default, revisions are sorted by reverse chronological order. However, keep in mind that Git dates may not be consistent across repositories. +- If serializeFormat is front-matter, this function can't work for .yml files. Use getFatDocHistory() instead. e.g.) foo.yml + ## Example @@ -69,7 +71,5 @@ Thus, a history is not [undefined, undefined, file_v2, undefined, file_v2, file_ [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.getoldrevision.md b/docs-api/git-documentdb.collection.getoldrevision.md index bf9ac218..4e387b88 100644 --- a/docs-api/git-documentdb.collection.getoldrevision.md +++ b/docs-api/git-documentdb.collection.getoldrevision.md @@ -20,7 +20,7 @@ getOldRevision(shortId: string, revision: number, historyOptions?: HistoryOption | Parameter | Type | Description | | --- | --- | --- | -| shortId | string | shortId is a file path whose collectionPath and .json extension are omitted. | +| shortId | string | shortId is a file path whose collectionPath and extension are omitted. | | revision | number | Specify a number to go back to old revision. Default is 0. See [Collection.getHistory()](./git-documentdb.collection.gethistory.md) for the array of revisions. | | historyOptions | [HistoryOptions](./git-documentdb.historyoptions.md) | The array of revisions is filtered by HistoryOptions.filter. | @@ -32,6 +32,8 @@ Promise<[JsonDoc](./git-documentdb.jsondoc.md) \| undefined> - undefined if a specified document does not exist or it is deleted. +- If serializeFormat is front-matter, this function can't correctly distinguish files that has the same \_id but different extension. Use getFatDocOldRevision() instead. e.g.) foo.md and foo.yml + ## Example @@ -45,7 +47,5 @@ collection.getOldRevision(_shortId, 2); // returns a document two revisions olde [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.collection.insert.md b/docs-api/git-documentdb.collection.insert.md index b5cf3fc2..b0bedd14 100644 --- a/docs-api/git-documentdb.collection.insert.md +++ b/docs-api/git-documentdb.collection.insert.md @@ -20,7 +20,7 @@ insert(jsonDoc: JsonDoc, options?: PutOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and extension are omitted. | | options | [PutOptions](./git-documentdb.putoptions.md) | | Returns: @@ -33,27 +33,29 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - If \_id is undefined, it is automatically generated. -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}${extension}` . ## Exceptions [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) (from putWorker) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) diff --git a/docs-api/git-documentdb.collection.insert_1.md b/docs-api/git-documentdb.collection.insert_1.md index 2b0dcec9..359bca77 100644 --- a/docs-api/git-documentdb.collection.insert_1.md +++ b/docs-api/git-documentdb.collection.insert_1.md @@ -20,7 +20,7 @@ insert(shortId: string | undefined | null, jsonDoc: JsonDoc, options?: PutOption | Parameter | Type | Description | | --- | --- | --- | -| shortId | string \| undefined \| null | shortId is a file path whose collectionPath and .json extension are omitted. | +| shortId | string \| undefined \| null | shortId is a file path whose collectionPath and extension are omitted. | | jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -32,7 +32,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - Throws SameIdExistsError when a document that has the same \_id exists. It might be better to use put() instead of insert(). -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}${extension}` . - If shortId is undefined, it is automatically generated. @@ -42,21 +42,23 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) (from putWorker) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) diff --git a/docs-api/git-documentdb.collection.insertfatdoc.md b/docs-api/git-documentdb.collection.insertfatdoc.md index e8746cd4..732f3592 100644 --- a/docs-api/git-documentdb.collection.insertfatdoc.md +++ b/docs-api/git-documentdb.collection.insertfatdoc.md @@ -20,7 +20,7 @@ insertFatDoc(shortName: string | undefined | null, doc: JsonDoc | string | Uint8 | Parameter | Type | Description | | --- | --- | --- | -| shortName | string \| undefined \| null | shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with .json extension. | +| shortName | string \| undefined \| null | shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with extension. | | doc | [JsonDoc](./git-documentdb.jsondoc.md) \| string \| Uint8Array | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -32,31 +32,33 @@ Promise<[PutResult](./git-documentdb.putresult.md) > - Throws SameIdExistsError when data that has the same \_id exists. It might be better to use put() instead of insert(). -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}${extension}` . - If shortName is undefined, it is automatically generated. -- \_id property of a JsonDoc is automatically set or overwritten by shortName parameter whose .json extension is omitted. +- \_id property of a JsonDoc is automatically set or overwritten by shortName parameter whose extension is omitted. ## Exceptions [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) (from putWorker) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) diff --git a/docs-api/git-documentdb.collection.md b/docs-api/git-documentdb.collection.md index e7a3d777..a13fecb8 100644 --- a/docs-api/git-documentdb.collection.md +++ b/docs-api/git-documentdb.collection.md @@ -23,7 +23,7 @@ export declare class Collection implements ICollection In a collection API, shortId (shortName) is used instead of \_id (name). -- shortId is a file path whose collectionPath and .json extension are omitted. (\_id = collectionPath + shortId) +- shortId is a file path whose collectionPath and extension are omitted. (\_id = collectionPath + shortId) - shortName is a file path whose collectionPath is omitted. (name = collectionPath + shortName) @@ -67,7 +67,7 @@ gitDDB.collection('Nara').get({ _id: 'flower' }); // returns { _id: 'flower', na | [deleteFatDoc(shortName, options)](./git-documentdb.collection.deletefatdoc.md) | | Delete a data | | [find(options)](./git-documentdb.collection.find.md) | | Get all the JSON documents | | [findFatDoc(options)](./git-documentdb.collection.findfatdoc.md) | | Get all the FatDoc data | -| [generateId()](./git-documentdb.collection.generateid.md) | | Generate new \_id as monotonic ULID | +| [generateId(seedTime)](./git-documentdb.collection.generateid.md) | | Generate new \_id as monotonic ULID | | [get(\_id)](./git-documentdb.collection.get.md) | | Get a JSON document | | [getCollections(dirPath)](./git-documentdb.collection.getcollections.md) | | Get collections directly under the specified dirPath. | | [getDocByOid(fileOid, docType)](./git-documentdb.collection.getdocbyoid.md) | | Get a Doc which has specified oid | diff --git a/docs-api/git-documentdb.collection.put.md b/docs-api/git-documentdb.collection.put.md index 088a30c3..1eabf22d 100644 --- a/docs-api/git-documentdb.collection.put.md +++ b/docs-api/git-documentdb.collection.put.md @@ -20,7 +20,7 @@ put(jsonDoc: JsonDoc, options?: PutOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and extension are omitted. | | options | [PutOptions](./git-documentdb.putoptions.md) | | Returns: @@ -29,7 +29,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > ## Remarks -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}${jsonDoc._id}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}${jsonDoc._id}${extension}` . - If \_id is undefined, it is automatically generated. @@ -37,19 +37,21 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) diff --git a/docs-api/git-documentdb.collection.put_1.md b/docs-api/git-documentdb.collection.put_1.md index cdb1ccdd..4bc2d035 100644 --- a/docs-api/git-documentdb.collection.put_1.md +++ b/docs-api/git-documentdb.collection.put_1.md @@ -20,7 +20,7 @@ put(shortId: string | undefined | null, jsonDoc: JsonDoc, options?: PutOptions): | Parameter | Type | Description | | --- | --- | --- | -| shortId | string \| undefined \| null | shortId is a file path whose collectionPath and .json extension are omitted. | +| shortId | string \| undefined \| null | shortId is a file path whose collectionPath and extension are omitted. | | jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -30,7 +30,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > ## Remarks -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}${extension}` . - If shortId is undefined, it is automatically generated. @@ -42,21 +42,21 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.InvalidCollectionPathCharacterError](./git-documentdb.err.invalidcollectionpathcharactererror.md) (from validateDocument, validateId) +\# Errors from validateDocument, validateId -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +\# Errors from putWorker -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) diff --git a/docs-api/git-documentdb.collection.putfatdoc.md b/docs-api/git-documentdb.collection.putfatdoc.md index db7fe58e..0d07f38b 100644 --- a/docs-api/git-documentdb.collection.putfatdoc.md +++ b/docs-api/git-documentdb.collection.putfatdoc.md @@ -20,7 +20,7 @@ putFatDoc(shortName: string | undefined | null, doc: JsonDoc | Uint8Array | stri | Parameter | Type | Description | | --- | --- | --- | -| shortName | string \| undefined \| null | shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with .json extension. | +| shortName | string \| undefined \| null | shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with extension. | | doc | [JsonDoc](./git-documentdb.jsondoc.md) \| Uint8Array \| string | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -30,11 +30,11 @@ Promise<[PutResult](./git-documentdb.putresult.md) > ## Remarks -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}${extension}` . - If shortName is undefined, it is automatically generated. -- \_id property of a JsonDoc is automatically set or overwritten by shortName parameter whose .json extension is omitted. +- \_id property of a JsonDoc is automatically set or overwritten by shortName parameter whose extension is omitted. - An update operation is not skipped even if no change occurred on a specified data. @@ -44,19 +44,21 @@ Promise<[PutResult](./git-documentdb.putresult.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) diff --git a/docs-api/git-documentdb.collection.update.md b/docs-api/git-documentdb.collection.update.md index cf2a0c31..41e8c3f8 100644 --- a/docs-api/git-documentdb.collection.update.md +++ b/docs-api/git-documentdb.collection.update.md @@ -20,7 +20,7 @@ update(jsonDoc: JsonDoc, options?: PutOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and extension are omitted. | | options | [PutOptions](./git-documentdb.putoptions.md) | | Returns: @@ -31,7 +31,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - Throws DocumentNotFoundError if a specified document does not exist. It might be better to use put() instead of update(). -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}${extension}` . - If \_id is undefined, it is automatically generated. @@ -41,21 +41,23 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) diff --git a/docs-api/git-documentdb.collection.update_1.md b/docs-api/git-documentdb.collection.update_1.md index 9020cd03..c6f78f73 100644 --- a/docs-api/git-documentdb.collection.update_1.md +++ b/docs-api/git-documentdb.collection.update_1.md @@ -32,7 +32,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - Throws DocumentNotFoundError if a specified data does not exist. It might be better to use put() instead of update(). -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}${extension}` . - An update operation is not skipped even if no change occurred on a specified data. @@ -40,21 +40,23 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) diff --git a/docs-api/git-documentdb.collection.updatefatdoc.md b/docs-api/git-documentdb.collection.updatefatdoc.md index 8171e1ce..cde510e3 100644 --- a/docs-api/git-documentdb.collection.updatefatdoc.md +++ b/docs-api/git-documentdb.collection.updatefatdoc.md @@ -20,7 +20,7 @@ updateFatDoc(shortName: string | undefined | null, doc: JsonDoc | string | Uint8 | Parameter | Type | Description | | --- | --- | --- | -| shortName | string \| undefined \| null | shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with .json extension. | +| shortName | string \| undefined \| null | shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with extension. | | doc | [JsonDoc](./git-documentdb.jsondoc.md) \| string \| Uint8Array | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -32,9 +32,9 @@ Promise<[PutResult](./git-documentdb.putresult.md) > - Throws DocumentNotFoundError if a specified data does not exist. It might be better to use put() instead of update(). -- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}${extension}` . -- \_id property of a JsonDoc is automatically set or overwritten by shortName parameter whose .json extension is omitted. +- \_id property of a JsonDoc is automatically set or overwritten by shortName parameter whose extension is omitted. - An update operation is not skipped even if no change occurred on a specified data. @@ -42,21 +42,23 @@ Promise<[PutResult](./git-documentdb.putresult.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) diff --git a/docs-api/git-documentdb.collectionoptions.md b/docs-api/git-documentdb.collectionoptions.md index c9e27222..d3d1193e 100644 --- a/docs-api/git-documentdb.collectionoptions.md +++ b/docs-api/git-documentdb.collectionoptions.md @@ -15,5 +15,14 @@ Options for Collection constructor ```typescript export declare type CollectionOptions = { namePrefix?: string; + debounceTime?: number; + idGenerator?: () => string; }; ``` + +## Remarks + +- namePrefix: Automatically generated \_id has a specified prefix in the collection. + +- debounceTime: put/insert/update operations for the same document are debounced by specified milliseconds in the collection. Default is -1 (do not debounce). + diff --git a/docs-api/git-documentdb.connectionsettingsgithub.md b/docs-api/git-documentdb.connectionsettingsgithub.md index 40ccf327..77ae60ec 100644 --- a/docs-api/git-documentdb.connectionsettingsgithub.md +++ b/docs-api/git-documentdb.connectionsettingsgithub.md @@ -15,6 +15,7 @@ Connection settings for GitHub ```typescript export declare type ConnectionSettingsGitHub = { type: 'github'; + engine?: string; personalAccessToken?: string; private?: boolean; }; diff --git a/docs-api/git-documentdb.connectionsettingsnone.md b/docs-api/git-documentdb.connectionsettingsnone.md index f5855a8f..13071f30 100644 --- a/docs-api/git-documentdb.connectionsettingsnone.md +++ b/docs-api/git-documentdb.connectionsettingsnone.md @@ -15,5 +15,6 @@ Connection settings do not exist. ```typescript export declare type ConnectionSettingsNone = { type: 'none'; + engine?: string; }; ``` diff --git a/docs-api/git-documentdb.connectionsettingsssh.md b/docs-api/git-documentdb.connectionsettingsssh.md index 55b11e4c..40e7a54d 100644 --- a/docs-api/git-documentdb.connectionsettingsssh.md +++ b/docs-api/git-documentdb.connectionsettingsssh.md @@ -15,6 +15,7 @@ Connection settings for SSH ```typescript export declare type ConnectionSettingsSSH = { type: 'ssh'; + engine?: string; privateKeyPath: string; publicKeyPath: string; passPhrase?: string; diff --git a/docs-api/git-documentdb.databaseinfo.md b/docs-api/git-documentdb.databaseinfo.md index 43bdc322..140876ad 100644 --- a/docs-api/git-documentdb.databaseinfo.md +++ b/docs-api/git-documentdb.databaseinfo.md @@ -17,8 +17,12 @@ export declare type DatabaseInfo = { dbId: string; creator: string; version: string; + serialize: SerializeFormatLabel; }; ``` +References: + +[SerializeFormatLabel](./git-documentdb.serializeformatlabel.md) ## Remarks @@ -32,3 +36,5 @@ export declare type DatabaseInfo = { - version: A version of the GitDocumentDB specification. The version can be used for database migration. +- serialize: Serialize format of the database. + diff --git a/docs-api/git-documentdb.databaseoptions.md b/docs-api/git-documentdb.databaseoptions.md index a3a8e137..ca81ee44 100644 --- a/docs-api/git-documentdb.databaseoptions.md +++ b/docs-api/git-documentdb.databaseoptions.md @@ -18,11 +18,14 @@ export declare type DatabaseOptions = { dbName: string; logLevel?: TLogLevelName; schema?: Schema; + serialize?: SerializeFormatLabel; + logToTransport?: (logObject: ILogObject) => void; + logColorEnabled?: boolean; }; ``` References: -[Schema](./git-documentdb.schema.md) +[Schema](./git-documentdb.schema.md) , [SerializeFormatLabel](./git-documentdb.serializeformatlabel.md) ## Remarks @@ -52,3 +55,11 @@ dbName - A name of a git repository logLevel - Default is 'info'. +schema - Schema for a specific document type. + +serializeFormat - Format for serialization + +logToTransport - logToTransport function for all log levels. See https://tslog.js.org/\#/?id=transports + +logColorEnabled - Enable color for console log. Default is true. When you write log into a file by logToTransport, false is recommended. + diff --git a/docs-api/git-documentdb.deleteresult.md b/docs-api/git-documentdb.deleteresult.md index a5340638..ab30642b 100644 --- a/docs-api/git-documentdb.deleteresult.md +++ b/docs-api/git-documentdb.deleteresult.md @@ -21,7 +21,7 @@ export declare type DeleteResult = DeleteResultJsonDoc | DeleteResultText | Dele ## Remarks -- \_id: \_id of a JSON document. This is a file name without .json extension. PutResult does not have \_id if a document is not [JsonDoc](./git-documentdb.jsondoc.md) type. +- \_id: \_id of a JSON document. This is a file name without extension. PutResult does not have \_id if a document is not [JsonDoc](./git-documentdb.jsondoc.md) type. - name: A file name in Git. e.g.) "foo.json", "bar/baz.md" diff --git a/docs-api/git-documentdb.encodetogitremotename.md b/docs-api/git-documentdb.encodetogitremotename.md new file mode 100644 index 00000000..5c118050 --- /dev/null +++ b/docs-api/git-documentdb.encodetogitremotename.md @@ -0,0 +1,44 @@ +--- +sidebar_label: encodeToGitRemoteName() function +title: encodeToGitRemoteName() function +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [encodeToGitRemoteName](./git-documentdb.encodetogitremotename.md) + +## encodeToGitRemoteName() function + +encodeToGitRemoteName + +Signature: + +```typescript +export declare function encodeToGitRemoteName(remoteURL: string): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| remoteURL | string | | + +Returns: + +string + +## Remarks + +The first default name of Git remote is "origin". + +GitDocumentDB adds an alias of "origin", whose name is generated automatically by this function. The second and subsequent remotes are also named in the same way. + +A remote name consists of \[remote address\]\_\[hash\]. Periods are replaced with underscores. e.g.) github\_com\_a0b1c23 It is human-readable. + +\[remote address\] is \[hostname + domain name\] or \[ip address\]. \[hash\] is calculated from remoteURL. + +\[hash\] is the first seven characters of SHA-1 so that it may collide. Capitalize one of the remote addresses when hashes collide because a hostname and a domain name are not case sensitive. + +## Exceptions + +[RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + diff --git a/docs-api/git-documentdb.err.cannotconnecterror._constructor_.md b/docs-api/git-documentdb.err.cannotconnecterror._constructor_.md deleted file mode 100644 index aac35d67..00000000 --- a/docs-api/git-documentdb.err.cannotconnecterror._constructor_.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.CannotConnectError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [CannotConnectError](./git-documentdb.err.cannotconnecterror.md) > [(constructor)](./git-documentdb.err.cannotconnecterror._constructor_.md) - -## Err.CannotConnectError.(constructor) - -Constructs a new instance of the `CannotConnectError` class - -Signature: - -```typescript -constructor(retry: number, url: string, mes: string); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| retry | number | | -| url | string | | -| mes | string | | - diff --git a/docs-api/git-documentdb.err.cannotconnecterror.md b/docs-api/git-documentdb.err.cannotconnecterror.md deleted file mode 100644 index 4b03228c..00000000 --- a/docs-api/git-documentdb.err.cannotconnecterror.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -sidebar_label: CannotConnectError -title: Err.CannotConnectError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [CannotConnectError](./git-documentdb.err.cannotconnecterror.md) - -## Err.CannotConnectError class - - -Signature: - -```typescript -export class CannotConnectError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(retry, url, mes)](./git-documentdb.err.cannotconnecterror._constructor_.md) | | Constructs a new instance of the CannotConnectError class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [retry](./git-documentdb.err.cannotconnecterror.retry.md) | | number | | - diff --git a/docs-api/git-documentdb.err.cannotconnecterror.retry.md b/docs-api/git-documentdb.err.cannotconnecterror.retry.md deleted file mode 100644 index c6355d77..00000000 --- a/docs-api/git-documentdb.err.cannotconnecterror.retry.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_label: retry -title: Err.CannotConnectError.retry property -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [CannotConnectError](./git-documentdb.err.cannotconnecterror.md) > [retry](./git-documentdb.err.cannotconnecterror.retry.md) - -## Err.CannotConnectError.retry property - -Signature: - -```typescript -retry: number; -``` diff --git a/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror._constructor_.md b/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror._constructor_.md new file mode 100644 index 00000000..bf4dde09 --- /dev/null +++ b/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror._constructor_.md @@ -0,0 +1,26 @@ +--- +sidebar_label: (constructor) +title: Err.CannotConnectRemoteRepositoryError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [CannotConnectRemoteRepositoryError](./git-documentdb.err.cannotconnectremoterepositoryerror.md) > [(constructor)](./git-documentdb.err.cannotconnectremoterepositoryerror._constructor_.md) + +## Err.CannotConnectRemoteRepositoryError.(constructor) + +Constructs a new instance of the `CannotConnectRemoteRepositoryError` class + +Signature: + +```typescript +constructor(retry: number, url: string, mes: string); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| retry | number | | +| url | string | | +| mes | string | | + diff --git a/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror.md b/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror.md new file mode 100644 index 00000000..ec9cc040 --- /dev/null +++ b/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror.md @@ -0,0 +1,32 @@ +--- +sidebar_label: CannotConnectRemoteRepositoryError +title: Err.CannotConnectRemoteRepositoryError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [CannotConnectRemoteRepositoryError](./git-documentdb.err.cannotconnectremoterepositoryerror.md) + +## Err.CannotConnectRemoteRepositoryError class + + +Signature: + +```typescript +export class CannotConnectRemoteRepositoryError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(retry, url, mes)](./git-documentdb.err.cannotconnectremoterepositoryerror._constructor_.md) | | Constructs a new instance of the CannotConnectRemoteRepositoryError class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [retry](./git-documentdb.err.cannotconnectremoterepositoryerror.retry.md) | | number | | + diff --git a/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror.retry.md b/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror.retry.md new file mode 100644 index 00000000..dfea0ce5 --- /dev/null +++ b/docs-api/git-documentdb.err.cannotconnectremoterepositoryerror.retry.md @@ -0,0 +1,15 @@ +--- +sidebar_label: retry +title: Err.CannotConnectRemoteRepositoryError.retry property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [CannotConnectRemoteRepositoryError](./git-documentdb.err.cannotconnectremoterepositoryerror.md) > [retry](./git-documentdb.err.cannotconnectremoterepositoryerror.retry.md) + +## Err.CannotConnectRemoteRepositoryError.retry property + +Signature: + +```typescript +retry: number; +``` diff --git a/docs-api/git-documentdb.err.fetchconnectionfailederror._constructor_.md b/docs-api/git-documentdb.err.fetchconnectionfailederror._constructor_.md deleted file mode 100644 index c8885d6c..00000000 --- a/docs-api/git-documentdb.err.fetchconnectionfailederror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.FetchConnectionFailedError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [FetchConnectionFailedError](./git-documentdb.err.fetchconnectionfailederror.md) > [(constructor)](./git-documentdb.err.fetchconnectionfailederror._constructor_.md) - -## Err.FetchConnectionFailedError.(constructor) - -Constructs a new instance of the `FetchConnectionFailedError` class - -Signature: - -```typescript -constructor(mes: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | unknown | | - diff --git a/docs-api/git-documentdb.err.fetchconnectionfailederror.md b/docs-api/git-documentdb.err.fetchconnectionfailederror.md deleted file mode 100644 index 78372aef..00000000 --- a/docs-api/git-documentdb.err.fetchconnectionfailederror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: FetchConnectionFailedError -title: Err.FetchConnectionFailedError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [FetchConnectionFailedError](./git-documentdb.err.fetchconnectionfailederror.md) - -## Err.FetchConnectionFailedError class - - -Signature: - -```typescript -export class FetchConnectionFailedError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.fetchconnectionfailederror._constructor_.md) | | Constructs a new instance of the FetchConnectionFailedError class | - diff --git a/docs-api/git-documentdb.err.fetchpermissiondeniederror._constructor_.md b/docs-api/git-documentdb.err.fetchpermissiondeniederror._constructor_.md deleted file mode 100644 index dd484292..00000000 --- a/docs-api/git-documentdb.err.fetchpermissiondeniederror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.FetchPermissionDeniedError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [FetchPermissionDeniedError](./git-documentdb.err.fetchpermissiondeniederror.md) > [(constructor)](./git-documentdb.err.fetchpermissiondeniederror._constructor_.md) - -## Err.FetchPermissionDeniedError.(constructor) - -Constructs a new instance of the `FetchPermissionDeniedError` class - -Signature: - -```typescript -constructor(mes: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | unknown | | - diff --git a/docs-api/git-documentdb.err.fetchpermissiondeniederror.md b/docs-api/git-documentdb.err.fetchpermissiondeniederror.md deleted file mode 100644 index 4a529771..00000000 --- a/docs-api/git-documentdb.err.fetchpermissiondeniederror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: FetchPermissionDeniedError -title: Err.FetchPermissionDeniedError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [FetchPermissionDeniedError](./git-documentdb.err.fetchpermissiondeniederror.md) - -## Err.FetchPermissionDeniedError class - - -Signature: - -```typescript -export class FetchPermissionDeniedError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.fetchpermissiondeniederror._constructor_.md) | | Constructs a new instance of the FetchPermissionDeniedError class | - diff --git a/docs-api/git-documentdb.err.gitpusherror._constructor_.md b/docs-api/git-documentdb.err.gitpusherror._constructor_.md deleted file mode 100644 index 56859ce6..00000000 --- a/docs-api/git-documentdb.err.gitpusherror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.GitPushError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [GitPushError](./git-documentdb.err.gitpusherror.md) > [(constructor)](./git-documentdb.err.gitpusherror._constructor_.md) - -## Err.GitPushError.(constructor) - -Constructs a new instance of the `GitPushError` class - -Signature: - -```typescript -constructor(mes: string); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | string | | - diff --git a/docs-api/git-documentdb.err.gitpusherror.md b/docs-api/git-documentdb.err.gitpusherror.md deleted file mode 100644 index 7c948c5a..00000000 --- a/docs-api/git-documentdb.err.gitpusherror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: GitPushError -title: Err.GitPushError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [GitPushError](./git-documentdb.err.gitpusherror.md) - -## Err.GitPushError class - - -Signature: - -```typescript -export class GitPushError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.gitpusherror._constructor_.md) | | Constructs a new instance of the GitPushError class | - diff --git a/docs-api/git-documentdb.err.httpnetworkerror._constructor_.md b/docs-api/git-documentdb.err.httpnetworkerror._constructor_.md deleted file mode 100644 index 36071f0f..00000000 --- a/docs-api/git-documentdb.err.httpnetworkerror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.HTTPNetworkError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [HTTPNetworkError](./git-documentdb.err.httpnetworkerror.md) > [(constructor)](./git-documentdb.err.httpnetworkerror._constructor_.md) - -## Err.HTTPNetworkError.(constructor) - -Constructs a new instance of the `HTTPNetworkError` class - -Signature: - -```typescript -constructor(mes: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | unknown | | - diff --git a/docs-api/git-documentdb.err.httpnetworkerror.md b/docs-api/git-documentdb.err.httpnetworkerror.md deleted file mode 100644 index bc667c42..00000000 --- a/docs-api/git-documentdb.err.httpnetworkerror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: HTTPNetworkError -title: Err.HTTPNetworkError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [HTTPNetworkError](./git-documentdb.err.httpnetworkerror.md) - -## Err.HTTPNetworkError class - - -Signature: - -```typescript -export class HTTPNetworkError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.httpnetworkerror._constructor_.md) | | Constructs a new instance of the HTTPNetworkError class | - diff --git a/docs-api/git-documentdb.err.invalidauthenticationtypeerror._constructor_.md b/docs-api/git-documentdb.err.invalidauthenticationtypeerror._constructor_.md deleted file mode 100644 index 855416fc..00000000 --- a/docs-api/git-documentdb.err.invalidauthenticationtypeerror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.InvalidAuthenticationTypeError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidAuthenticationTypeError](./git-documentdb.err.invalidauthenticationtypeerror.md) > [(constructor)](./git-documentdb.err.invalidauthenticationtypeerror._constructor_.md) - -## Err.InvalidAuthenticationTypeError.(constructor) - -Constructs a new instance of the `InvalidAuthenticationTypeError` class - -Signature: - -```typescript -constructor(type: string); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | | - diff --git a/docs-api/git-documentdb.err.invalidauthenticationtypeerror.md b/docs-api/git-documentdb.err.invalidauthenticationtypeerror.md deleted file mode 100644 index e074c4e6..00000000 --- a/docs-api/git-documentdb.err.invalidauthenticationtypeerror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: InvalidAuthenticationTypeError -title: Err.InvalidAuthenticationTypeError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidAuthenticationTypeError](./git-documentdb.err.invalidauthenticationtypeerror.md) - -## Err.InvalidAuthenticationTypeError class - - -Signature: - -```typescript -export class InvalidAuthenticationTypeError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(type)](./git-documentdb.err.invalidauthenticationtypeerror._constructor_.md) | | Constructs a new instance of the InvalidAuthenticationTypeError class | - diff --git a/docs-api/git-documentdb.err.invalidconflictresolutionstrategyerror._constructor_.md b/docs-api/git-documentdb.err.invalidconflictresolutionstrategyerror._constructor_.md new file mode 100644 index 00000000..05d08ca5 --- /dev/null +++ b/docs-api/git-documentdb.err.invalidconflictresolutionstrategyerror._constructor_.md @@ -0,0 +1,17 @@ +--- +sidebar_label: (constructor) +title: Err.InvalidConflictResolutionStrategyError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidConflictResolutionStrategyError](./git-documentdb.err.invalidconflictresolutionstrategyerror.md) > [(constructor)](./git-documentdb.err.invalidconflictresolutionstrategyerror._constructor_.md) + +## Err.InvalidConflictResolutionStrategyError.(constructor) + +Constructs a new instance of the `InvalidConflictResolutionStrategyError` class + +Signature: + +```typescript +constructor(); +``` diff --git a/docs-api/git-documentdb.err.invalidconflictresolutionstrategyerror.md b/docs-api/git-documentdb.err.invalidconflictresolutionstrategyerror.md new file mode 100644 index 00000000..63e2e706 --- /dev/null +++ b/docs-api/git-documentdb.err.invalidconflictresolutionstrategyerror.md @@ -0,0 +1,26 @@ +--- +sidebar_label: InvalidConflictResolutionStrategyError +title: Err.InvalidConflictResolutionStrategyError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidConflictResolutionStrategyError](./git-documentdb.err.invalidconflictresolutionstrategyerror.md) + +## Err.InvalidConflictResolutionStrategyError class + + +Signature: + +```typescript +export class InvalidConflictResolutionStrategyError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./git-documentdb.err.invalidconflictresolutionstrategyerror._constructor_.md) | | Constructs a new instance of the InvalidConflictResolutionStrategyError class | + diff --git a/docs-api/git-documentdb.err.invalidrepositoryurlerror._constructor_.md b/docs-api/git-documentdb.err.invalidrepositoryurlerror._constructor_.md deleted file mode 100644 index 45381d50..00000000 --- a/docs-api/git-documentdb.err.invalidrepositoryurlerror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.InvalidRepositoryURLError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidRepositoryURLError](./git-documentdb.err.invalidrepositoryurlerror.md) > [(constructor)](./git-documentdb.err.invalidrepositoryurlerror._constructor_.md) - -## Err.InvalidRepositoryURLError.(constructor) - -Constructs a new instance of the `InvalidRepositoryURLError` class - -Signature: - -```typescript -constructor(url: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | unknown | | - diff --git a/docs-api/git-documentdb.err.invalidrepositoryurlerror.md b/docs-api/git-documentdb.err.invalidrepositoryurlerror.md deleted file mode 100644 index 67b3e7d4..00000000 --- a/docs-api/git-documentdb.err.invalidrepositoryurlerror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: InvalidRepositoryURLError -title: Err.InvalidRepositoryURLError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidRepositoryURLError](./git-documentdb.err.invalidrepositoryurlerror.md) - -## Err.InvalidRepositoryURLError class - - -Signature: - -```typescript -export class InvalidRepositoryURLError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(url)](./git-documentdb.err.invalidrepositoryurlerror._constructor_.md) | | Constructs a new instance of the InvalidRepositoryURLError class | - diff --git a/docs-api/git-documentdb.err.invalidsshkeypatherror._constructor_.md b/docs-api/git-documentdb.err.invalidsshkeypatherror._constructor_.md deleted file mode 100644 index 0824a8fa..00000000 --- a/docs-api/git-documentdb.err.invalidsshkeypatherror._constructor_.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.InvalidSSHKeyPathError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidSSHKeyPathError](./git-documentdb.err.invalidsshkeypatherror.md) > [(constructor)](./git-documentdb.err.invalidsshkeypatherror._constructor_.md) - -## Err.InvalidSSHKeyPathError.(constructor) - -Constructs a new instance of the `InvalidSSHKeyPathError` class - -Signature: - -```typescript -constructor(); -``` diff --git a/docs-api/git-documentdb.err.invalidsshkeypatherror.md b/docs-api/git-documentdb.err.invalidsshkeypatherror.md deleted file mode 100644 index c25c5488..00000000 --- a/docs-api/git-documentdb.err.invalidsshkeypatherror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: InvalidSSHKeyPathError -title: Err.InvalidSSHKeyPathError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidSSHKeyPathError](./git-documentdb.err.invalidsshkeypatherror.md) - -## Err.InvalidSSHKeyPathError class - - -Signature: - -```typescript -export class InvalidSSHKeyPathError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)()](./git-documentdb.err.invalidsshkeypatherror._constructor_.md) | | Constructs a new instance of the InvalidSSHKeyPathError class | - diff --git a/docs-api/git-documentdb.err.invalidurlerror._constructor_.md b/docs-api/git-documentdb.err.invalidurlerror._constructor_.md deleted file mode 100644 index 8f1a9be3..00000000 --- a/docs-api/git-documentdb.err.invalidurlerror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.InvalidURLError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidURLError](./git-documentdb.err.invalidurlerror.md) > [(constructor)](./git-documentdb.err.invalidurlerror._constructor_.md) - -## Err.InvalidURLError.(constructor) - -Constructs a new instance of the `InvalidURLError` class - -Signature: - -```typescript -constructor(url: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | unknown | | - diff --git a/docs-api/git-documentdb.err.invalidurlerror.md b/docs-api/git-documentdb.err.invalidurlerror.md deleted file mode 100644 index b5ee3519..00000000 --- a/docs-api/git-documentdb.err.invalidurlerror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: InvalidURLError -title: Err.InvalidURLError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [InvalidURLError](./git-documentdb.err.invalidurlerror.md) - -## Err.InvalidURLError class - - -Signature: - -```typescript -export class InvalidURLError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(url)](./git-documentdb.err.invalidurlerror._constructor_.md) | | Constructs a new instance of the InvalidURLError class | - diff --git a/docs-api/git-documentdb.err.md b/docs-api/git-documentdb.err.md index 5ae41261..1a5146cf 100644 --- a/docs-api/git-documentdb.err.md +++ b/docs-api/git-documentdb.err.md @@ -22,7 +22,7 @@ export declare namespace Err | --- | --- | | [AuthenticationTypeNotAllowCreateRepositoryError](./git-documentdb.err.authenticationtypenotallowcreaterepositoryerror.md) | | | [BaseError](./git-documentdb.err.baseerror.md) | BaseError | -| [CannotConnectError](./git-documentdb.err.cannotconnecterror.md) | | +| [CannotConnectRemoteRepositoryError](./git-documentdb.err.cannotconnectremoterepositoryerror.md) | | | [CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) | | | [CannotCreateRemoteRepositoryError](./git-documentdb.err.cannotcreateremoterepositoryerror.md) | | | [CannotCreateRepositoryError](./git-documentdb.err.cannotcreaterepositoryerror.md) | | @@ -34,17 +34,13 @@ export declare namespace Err | [DatabaseCloseTimeoutError](./git-documentdb.err.databaseclosetimeouterror.md) | | | [DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) | | | [DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) | | -| [FetchConnectionFailedError](./git-documentdb.err.fetchconnectionfailederror.md) | | -| [FetchPermissionDeniedError](./git-documentdb.err.fetchpermissiondeniederror.md) | | | [FileRemoveTimeoutError](./git-documentdb.err.fileremovetimeouterror.md) | | | [GitMergeBranchError](./git-documentdb.err.gitmergebrancherror.md) | | -| [GitPushError](./git-documentdb.err.gitpusherror.md) | | -| [HTTPNetworkError](./git-documentdb.err.httpnetworkerror.md) | | | [HttpProtocolRequiredError](./git-documentdb.err.httpprotocolrequirederror.md) | | | [IntervalTooSmallError](./git-documentdb.err.intervaltoosmallerror.md) | | -| [InvalidAuthenticationTypeError](./git-documentdb.err.invalidauthenticationtypeerror.md) | | | [InvalidCollectionPathCharacterError](./git-documentdb.err.invalidcollectionpathcharactererror.md) | | | [InvalidCollectionPathLengthError](./git-documentdb.err.invalidcollectionpathlengtherror.md) | | +| [InvalidConflictResolutionStrategyError](./git-documentdb.err.invalidconflictresolutionstrategyerror.md) | | | [InvalidConflictStateError](./git-documentdb.err.invalidconflictstateerror.md) | | | [InvalidDbNameCharacterError](./git-documentdb.err.invaliddbnamecharactererror.md) | | | [InvalidDocTypeError](./git-documentdb.err.invaliddoctypeerror.md) | | @@ -53,19 +49,12 @@ export declare namespace Err | [InvalidJsonFileExtensionError](./git-documentdb.err.invalidjsonfileextensionerror.md) | | | [InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) | | | [InvalidLocalDirCharacterError](./git-documentdb.err.invalidlocaldircharactererror.md) | | -| [InvalidRepositoryURLError](./git-documentdb.err.invalidrepositoryurlerror.md) | | -| [InvalidSSHKeyPathError](./git-documentdb.err.invalidsshkeypatherror.md) | | -| [InvalidURLError](./git-documentdb.err.invalidurlerror.md) | | | [InvalidWorkingDirectoryPathLengthError](./git-documentdb.err.invalidworkingdirectorypathlengtherror.md) | | | [NoMergeBaseFoundError](./git-documentdb.err.nomergebasefounderror.md) | | | [PersonalAccessTokenForAnotherAccountError](./git-documentdb.err.personalaccesstokenforanotheraccounterror.md) | | -| [PushConnectionFailedError](./git-documentdb.err.pushconnectionfailederror.md) | | | [PushNotAllowedError](./git-documentdb.err.pushnotallowederror.md) | | -| [PushPermissionDeniedError](./git-documentdb.err.pushpermissiondeniederror.md) | | | [PushWorkerError](./git-documentdb.err.pushworkererror.md) | | | [RemoteAlreadyRegisteredError](./git-documentdb.err.remotealreadyregisterederror.md) | | -| [RemoteRepositoryConnectError](./git-documentdb.err.remoterepositoryconnecterror.md) | | -| [RemoteRepositoryNotFoundError](./git-documentdb.err.remoterepositorynotfounderror.md) | | | [RepositoryNotFoundError](./git-documentdb.err.repositorynotfounderror.md) | | | [RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) | | | [RequestTimeoutError](./git-documentdb.err.requesttimeouterror.md) | | @@ -73,7 +62,6 @@ export declare namespace Err | [SocketTimeoutError](./git-documentdb.err.sockettimeouterror.md) | | | [SyncIntervalLessThanOrEqualToRetryIntervalError](./git-documentdb.err.syncintervallessthanorequaltoretryintervalerror.md) | | | [SyncWorkerError](./git-documentdb.err.syncworkererror.md) | | -| [SyncWorkerFetchError](./git-documentdb.err.syncworkerfetcherror.md) | | | [TaskCancelError](./git-documentdb.err.taskcancelerror.md) | | | [ThreeWayMergeError](./git-documentdb.err.threewaymergeerror.md) | | | [UndefinedDatabaseNameError](./git-documentdb.err.undefineddatabasenameerror.md) | | @@ -82,5 +70,4 @@ export declare namespace Err | [UndefinedPersonalAccessTokenError](./git-documentdb.err.undefinedpersonalaccesstokenerror.md) | | | [UndefinedRemoteURLError](./git-documentdb.err.undefinedremoteurlerror.md) | | | [UndefinedSyncError](./git-documentdb.err.undefinedsyncerror.md) | | -| [UnfetchedCommitExistsError](./git-documentdb.err.unfetchedcommitexistserror.md) | | diff --git a/docs-api/git-documentdb.err.pushconnectionfailederror._constructor_.md b/docs-api/git-documentdb.err.pushconnectionfailederror._constructor_.md deleted file mode 100644 index a4ea2a52..00000000 --- a/docs-api/git-documentdb.err.pushconnectionfailederror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.PushConnectionFailedError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [PushConnectionFailedError](./git-documentdb.err.pushconnectionfailederror.md) > [(constructor)](./git-documentdb.err.pushconnectionfailederror._constructor_.md) - -## Err.PushConnectionFailedError.(constructor) - -Constructs a new instance of the `PushConnectionFailedError` class - -Signature: - -```typescript -constructor(mes: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | unknown | | - diff --git a/docs-api/git-documentdb.err.pushconnectionfailederror.md b/docs-api/git-documentdb.err.pushconnectionfailederror.md deleted file mode 100644 index af63945d..00000000 --- a/docs-api/git-documentdb.err.pushconnectionfailederror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: PushConnectionFailedError -title: Err.PushConnectionFailedError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [PushConnectionFailedError](./git-documentdb.err.pushconnectionfailederror.md) - -## Err.PushConnectionFailedError class - - -Signature: - -```typescript -export class PushConnectionFailedError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.pushconnectionfailederror._constructor_.md) | | Constructs a new instance of the PushConnectionFailedError class | - diff --git a/docs-api/git-documentdb.err.pushpermissiondeniederror._constructor_.md b/docs-api/git-documentdb.err.pushpermissiondeniederror._constructor_.md deleted file mode 100644 index 7dfb4ed6..00000000 --- a/docs-api/git-documentdb.err.pushpermissiondeniederror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.PushPermissionDeniedError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [PushPermissionDeniedError](./git-documentdb.err.pushpermissiondeniederror.md) > [(constructor)](./git-documentdb.err.pushpermissiondeniederror._constructor_.md) - -## Err.PushPermissionDeniedError.(constructor) - -Constructs a new instance of the `PushPermissionDeniedError` class - -Signature: - -```typescript -constructor(mes: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | unknown | | - diff --git a/docs-api/git-documentdb.err.pushpermissiondeniederror.md b/docs-api/git-documentdb.err.pushpermissiondeniederror.md deleted file mode 100644 index e6d7775f..00000000 --- a/docs-api/git-documentdb.err.pushpermissiondeniederror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: PushPermissionDeniedError -title: Err.PushPermissionDeniedError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [PushPermissionDeniedError](./git-documentdb.err.pushpermissiondeniederror.md) - -## Err.PushPermissionDeniedError class - - -Signature: - -```typescript -export class PushPermissionDeniedError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.pushpermissiondeniederror._constructor_.md) | | Constructs a new instance of the PushPermissionDeniedError class | - diff --git a/docs-api/git-documentdb.err.remoterepositoryconnecterror._constructor_.md b/docs-api/git-documentdb.err.remoterepositoryconnecterror._constructor_.md deleted file mode 100644 index e274fe74..00000000 --- a/docs-api/git-documentdb.err.remoterepositoryconnecterror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.RemoteRepositoryConnectError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [RemoteRepositoryConnectError](./git-documentdb.err.remoterepositoryconnecterror.md) > [(constructor)](./git-documentdb.err.remoterepositoryconnecterror._constructor_.md) - -## Err.RemoteRepositoryConnectError.(constructor) - -Constructs a new instance of the `RemoteRepositoryConnectError` class - -Signature: - -```typescript -constructor(mes: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | unknown | | - diff --git a/docs-api/git-documentdb.err.remoterepositoryconnecterror.md b/docs-api/git-documentdb.err.remoterepositoryconnecterror.md deleted file mode 100644 index 5c1c6f1c..00000000 --- a/docs-api/git-documentdb.err.remoterepositoryconnecterror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: RemoteRepositoryConnectError -title: Err.RemoteRepositoryConnectError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [RemoteRepositoryConnectError](./git-documentdb.err.remoterepositoryconnecterror.md) - -## Err.RemoteRepositoryConnectError class - - -Signature: - -```typescript -export class RemoteRepositoryConnectError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.remoterepositoryconnecterror._constructor_.md) | | Constructs a new instance of the RemoteRepositoryConnectError class | - diff --git a/docs-api/git-documentdb.err.remoterepositorynotfounderror._constructor_.md b/docs-api/git-documentdb.err.remoterepositorynotfounderror._constructor_.md deleted file mode 100644 index 98ebc277..00000000 --- a/docs-api/git-documentdb.err.remoterepositorynotfounderror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.RemoteRepositoryNotFoundError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [RemoteRepositoryNotFoundError](./git-documentdb.err.remoterepositorynotfounderror.md) > [(constructor)](./git-documentdb.err.remoterepositorynotfounderror._constructor_.md) - -## Err.RemoteRepositoryNotFoundError.(constructor) - -Constructs a new instance of the `RemoteRepositoryNotFoundError` class - -Signature: - -```typescript -constructor(url: unknown); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | unknown | | - diff --git a/docs-api/git-documentdb.err.remoterepositorynotfounderror.md b/docs-api/git-documentdb.err.remoterepositorynotfounderror.md deleted file mode 100644 index 644d7b6e..00000000 --- a/docs-api/git-documentdb.err.remoterepositorynotfounderror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: RemoteRepositoryNotFoundError -title: Err.RemoteRepositoryNotFoundError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [RemoteRepositoryNotFoundError](./git-documentdb.err.remoterepositorynotfounderror.md) - -## Err.RemoteRepositoryNotFoundError class - - -Signature: - -```typescript -export class RemoteRepositoryNotFoundError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(url)](./git-documentdb.err.remoterepositorynotfounderror._constructor_.md) | | Constructs a new instance of the RemoteRepositoryNotFoundError class | - diff --git a/docs-api/git-documentdb.err.syncworkerfetcherror._constructor_.md b/docs-api/git-documentdb.err.syncworkerfetcherror._constructor_.md deleted file mode 100644 index afa2d5e5..00000000 --- a/docs-api/git-documentdb.err.syncworkerfetcherror._constructor_.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.SyncWorkerFetchError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [SyncWorkerFetchError](./git-documentdb.err.syncworkerfetcherror.md) > [(constructor)](./git-documentdb.err.syncworkerfetcherror._constructor_.md) - -## Err.SyncWorkerFetchError.(constructor) - -Constructs a new instance of the `SyncWorkerFetchError` class - -Signature: - -```typescript -constructor(mes: string); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| mes | string | | - diff --git a/docs-api/git-documentdb.err.syncworkerfetcherror.md b/docs-api/git-documentdb.err.syncworkerfetcherror.md deleted file mode 100644 index 73ef83b9..00000000 --- a/docs-api/git-documentdb.err.syncworkerfetcherror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: SyncWorkerFetchError -title: Err.SyncWorkerFetchError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [SyncWorkerFetchError](./git-documentdb.err.syncworkerfetcherror.md) - -## Err.SyncWorkerFetchError class - - -Signature: - -```typescript -export class SyncWorkerFetchError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(mes)](./git-documentdb.err.syncworkerfetcherror._constructor_.md) | | Constructs a new instance of the SyncWorkerFetchError class | - diff --git a/docs-api/git-documentdb.err.unfetchedcommitexistserror._constructor_.md b/docs-api/git-documentdb.err.unfetchedcommitexistserror._constructor_.md deleted file mode 100644 index 8c0d3879..00000000 --- a/docs-api/git-documentdb.err.unfetchedcommitexistserror._constructor_.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar_label: (constructor) -title: Err.UnfetchedCommitExistsError.(constructor) -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [UnfetchedCommitExistsError](./git-documentdb.err.unfetchedcommitexistserror.md) > [(constructor)](./git-documentdb.err.unfetchedcommitexistserror._constructor_.md) - -## Err.UnfetchedCommitExistsError.(constructor) - -Constructs a new instance of the `UnfetchedCommitExistsError` class - -Signature: - -```typescript -constructor(); -``` diff --git a/docs-api/git-documentdb.err.unfetchedcommitexistserror.md b/docs-api/git-documentdb.err.unfetchedcommitexistserror.md deleted file mode 100644 index e14b9756..00000000 --- a/docs-api/git-documentdb.err.unfetchedcommitexistserror.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: UnfetchedCommitExistsError -title: Err.UnfetchedCommitExistsError class -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Err](./git-documentdb.err.md) > [UnfetchedCommitExistsError](./git-documentdb.err.unfetchedcommitexistserror.md) - -## Err.UnfetchedCommitExistsError class - - -Signature: - -```typescript -export class UnfetchedCommitExistsError extends BaseError -``` -Extends: - -BaseError - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)()](./git-documentdb.err.unfetchedcommitexistserror._constructor_.md) | | Constructs a new instance of the UnfetchedCommitExistsError class | - diff --git a/docs-api/git-documentdb.file_create_timeout.md b/docs-api/git-documentdb.file_create_timeout.md new file mode 100644 index 00000000..1520445c --- /dev/null +++ b/docs-api/git-documentdb.file_create_timeout.md @@ -0,0 +1,16 @@ +--- +sidebar_label: FILE_CREATE_TIMEOUT variable +title: FILE_CREATE_TIMEOUT variable +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [FILE\_CREATE\_TIMEOUT](./git-documentdb.file_create_timeout.md) + +## FILE\_CREATE\_TIMEOUT variable + + +Signature: + +```typescript +FILE_CREATE_TIMEOUT = 2000 +``` diff --git a/docs-api/git-documentdb.front_matter_postfix.md b/docs-api/git-documentdb.front_matter_postfix.md new file mode 100644 index 00000000..3d1c9d4e --- /dev/null +++ b/docs-api/git-documentdb.front_matter_postfix.md @@ -0,0 +1,16 @@ +--- +sidebar_label: FRONT_MATTER_POSTFIX variable +title: FRONT_MATTER_POSTFIX variable +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [FRONT\_MATTER\_POSTFIX](./git-documentdb.front_matter_postfix.md) + +## FRONT\_MATTER\_POSTFIX variable + + +Signature: + +```typescript +FRONT_MATTER_POSTFIX = ".md" +``` diff --git a/docs-api/git-documentdb.git_documentdb_app_info_id.md b/docs-api/git-documentdb.git_documentdb_app_info_id.md deleted file mode 100644 index 80baf4b1..00000000 --- a/docs-api/git-documentdb.git_documentdb_app_info_id.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -sidebar_label: GIT_DOCUMENTDB_APP_INFO_ID variable -title: GIT_DOCUMENTDB_APP_INFO_ID variable -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GIT\_DOCUMENTDB\_APP\_INFO\_ID](./git-documentdb.git_documentdb_app_info_id.md) - -## GIT\_DOCUMENTDB\_APP\_INFO\_ID variable - - -Signature: - -```typescript -GIT_DOCUMENTDB_APP_INFO_ID = ".gitddb/app" -``` diff --git a/docs-api/git-documentdb.gitddbinterface.defaultbranch.md b/docs-api/git-documentdb.gitddbinterface.defaultbranch.md index 5840f158..cb320c6e 100644 --- a/docs-api/git-documentdb.gitddbinterface.defaultbranch.md +++ b/docs-api/git-documentdb.gitddbinterface.defaultbranch.md @@ -8,8 +8,6 @@ hide_title: true ## GitDDBInterface.defaultBranch property -\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties (readonly) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* - Signature: ```typescript diff --git a/docs-api/git-documentdb.gitddbinterface.loadappinfo.md b/docs-api/git-documentdb.gitddbinterface.loadappinfo.md deleted file mode 100644 index 5eb7a41a..00000000 --- a/docs-api/git-documentdb.gitddbinterface.loadappinfo.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -sidebar_label: loadAppInfo() -title: GitDDBInterface.loadAppInfo() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDDBInterface](./git-documentdb.gitddbinterface.md) > [loadAppInfo](./git-documentdb.gitddbinterface.loadappinfo.md) - -## GitDDBInterface.loadAppInfo() method - -Signature: - -```typescript -loadAppInfo(): { - [key: string]: any; - }; -``` -Returns: - -{ \[key: string\]: any; } - diff --git a/docs-api/git-documentdb.gitddbinterface.logger.md b/docs-api/git-documentdb.gitddbinterface.logger.md index 389269e0..9bc214fa 100644 --- a/docs-api/git-documentdb.gitddbinterface.logger.md +++ b/docs-api/git-documentdb.gitddbinterface.logger.md @@ -11,5 +11,5 @@ hide_title: true Signature: ```typescript -logger: Logger; +logger: ColoredLogger; ``` diff --git a/docs-api/git-documentdb.gitddbinterface.md b/docs-api/git-documentdb.gitddbinterface.md index 3aeeb090..1df04f83 100644 --- a/docs-api/git-documentdb.gitddbinterface.md +++ b/docs-api/git-documentdb.gitddbinterface.md @@ -24,15 +24,17 @@ export interface GitDDBInterface | [committer](./git-documentdb.gitddbinterface.committer.md) | { name: string; email: string; } | | | [dbId](./git-documentdb.gitddbinterface.dbid.md) | string | | | [dbName](./git-documentdb.gitddbinterface.dbname.md) | string | | -| [defaultBranch](./git-documentdb.gitddbinterface.defaultbranch.md) | string | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties (readonly) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | +| [defaultBranch](./git-documentdb.gitddbinterface.defaultbranch.md) | string | | | [isClosing](./git-documentdb.gitddbinterface.isclosing.md) | boolean | | | [isOpened](./git-documentdb.gitddbinterface.isopened.md) | boolean | | | [localDir](./git-documentdb.gitddbinterface.localdir.md) | string | | -| [logger](./git-documentdb.gitddbinterface.logger.md) | Logger | | +| [logger](./git-documentdb.gitddbinterface.logger.md) | ColoredLogger | | | [logLevel](./git-documentdb.gitddbinterface.loglevel.md) | TLogLevelName | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | | [rootCollection](./git-documentdb.gitddbinterface.rootcollection.md) | [ICollection](./git-documentdb.icollection.md) | | | [schema](./git-documentdb.gitddbinterface.schema.md) | [Schema](./git-documentdb.schema.md) | | +| [serializeFormat](./git-documentdb.gitddbinterface.serializeformat.md) | SerializeFormatJSON \| SerializeFormatFrontMatter | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties (readonly) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | | [taskQueue](./git-documentdb.gitddbinterface.taskqueue.md) | [TaskQueue](./git-documentdb.taskqueue.md) | | +| [tsLogger](./git-documentdb.gitddbinterface.tslogger.md) | Logger | | | [validator](./git-documentdb.gitddbinterface.validator.md) | [Validator](./git-documentdb.validator.md) | | | [workingDir](./git-documentdb.gitddbinterface.workingdir.md) | string | | @@ -45,15 +47,11 @@ export interface GitDDBInterface | [getCommit(oid)](./git-documentdb.gitddbinterface.getcommit.md) | | | [getRemoteURLs()](./git-documentdb.gitddbinterface.getremoteurls.md) | | | [getSync(remoteURL)](./git-documentdb.gitddbinterface.getsync.md) | | -| [loadAppInfo()](./git-documentdb.gitddbinterface.loadappinfo.md) | | | [loadAuthor()](./git-documentdb.gitddbinterface.loadauthor.md) | | | [loadDbInfo()](./git-documentdb.gitddbinterface.loaddbinfo.md) | | | [open(options)](./git-documentdb.gitddbinterface.open.md) | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public methods \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | | [removeSync(remoteURL)](./git-documentdb.gitddbinterface.removesync.md) | | -| [repository()](./git-documentdb.gitddbinterface.repository.md) | | -| [saveAppInfo(info)](./git-documentdb.gitddbinterface.saveappinfo.md) | | | [saveAuthor()](./git-documentdb.gitddbinterface.saveauthor.md) | | -| [setRepository(repos)](./git-documentdb.gitddbinterface.setrepository.md) | | | [sync(options, getSyncResult)](./git-documentdb.gitddbinterface.sync.md) | | | [sync(options)](./git-documentdb.gitddbinterface.sync_1.md) | | diff --git a/docs-api/git-documentdb.gitddbinterface.repository.md b/docs-api/git-documentdb.gitddbinterface.repository.md deleted file mode 100644 index 19f775da..00000000 --- a/docs-api/git-documentdb.gitddbinterface.repository.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_label: repository() -title: GitDDBInterface.repository() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDDBInterface](./git-documentdb.gitddbinterface.md) > [repository](./git-documentdb.gitddbinterface.repository.md) - -## GitDDBInterface.repository() method - -Signature: - -```typescript -repository(): nodegit.Repository | undefined; -``` -Returns: - -nodegit.Repository \| undefined - diff --git a/docs-api/git-documentdb.gitddbinterface.saveappinfo.md b/docs-api/git-documentdb.gitddbinterface.saveappinfo.md deleted file mode 100644 index 5c2a9f3f..00000000 --- a/docs-api/git-documentdb.gitddbinterface.saveappinfo.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -sidebar_label: saveAppInfo() -title: GitDDBInterface.saveAppInfo() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDDBInterface](./git-documentdb.gitddbinterface.md) > [saveAppInfo](./git-documentdb.gitddbinterface.saveappinfo.md) - -## GitDDBInterface.saveAppInfo() method - -Signature: - -```typescript -saveAppInfo(info: { - [key: string]: any; - }): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| info | { \[key: string\]: any; } | | - -Returns: - -void - diff --git a/docs-api/git-documentdb.gitddbinterface.serializeformat.md b/docs-api/git-documentdb.gitddbinterface.serializeformat.md new file mode 100644 index 00000000..c3fbfbf3 --- /dev/null +++ b/docs-api/git-documentdb.gitddbinterface.serializeformat.md @@ -0,0 +1,17 @@ +--- +sidebar_label: serializeFormat +title: GitDDBInterface.serializeFormat property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDDBInterface](./git-documentdb.gitddbinterface.md) > [serializeFormat](./git-documentdb.gitddbinterface.serializeformat.md) + +## GitDDBInterface.serializeFormat property + +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties (readonly) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* + +Signature: + +```typescript +serializeFormat: SerializeFormatJSON | SerializeFormatFrontMatter; +``` diff --git a/docs-api/git-documentdb.gitddbinterface.setrepository.md b/docs-api/git-documentdb.gitddbinterface.setrepository.md deleted file mode 100644 index 368c6bb4..00000000 --- a/docs-api/git-documentdb.gitddbinterface.setrepository.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: setRepository() -title: GitDDBInterface.setRepository() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDDBInterface](./git-documentdb.gitddbinterface.md) > [setRepository](./git-documentdb.gitddbinterface.setrepository.md) - -## GitDDBInterface.setRepository() method - -Signature: - -```typescript -setRepository(repos: nodegit.Repository): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| repos | nodegit.Repository | | - -Returns: - -void - diff --git a/docs-api/git-documentdb.gitddbinterface.tslogger.md b/docs-api/git-documentdb.gitddbinterface.tslogger.md new file mode 100644 index 00000000..a56cf3af --- /dev/null +++ b/docs-api/git-documentdb.gitddbinterface.tslogger.md @@ -0,0 +1,15 @@ +--- +sidebar_label: tsLogger +title: GitDDBInterface.tsLogger property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDDBInterface](./git-documentdb.gitddbinterface.md) > [tsLogger](./git-documentdb.gitddbinterface.tslogger.md) + +## GitDDBInterface.tsLogger property + +Signature: + +```typescript +tsLogger: Logger; +``` diff --git a/docs-api/git-documentdb.gitdocumentdb.delete.md b/docs-api/git-documentdb.gitdocumentdb.delete.md index 09dbb3d0..461aca39 100644 --- a/docs-api/git-documentdb.gitdocumentdb.delete.md +++ b/docs-api/git-documentdb.gitdocumentdb.delete.md @@ -20,7 +20,7 @@ delete(_id: string, options?: DeleteOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| \_id | string | \_id is a file path whose .json extension is omitted. | +| \_id | string | \_id is a file path whose extension is omitted. | | options | [DeleteOptions](./git-documentdb.deleteoptions.md) | | Returns: @@ -33,17 +33,17 @@ Promise<[DeleteResultJsonDoc](./git-documentdb.deleteresultjsondoc.md) > ## Exceptions -[Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) (from Collection\#delete) +[Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (from deleteImpl) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from deleteImpl) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (from deleteWorker) +\# Errors from deleteWorker -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (from deleteWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) (from deleteWorker) +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) -[Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) (from deleteWorker) +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.delete_1.md b/docs-api/git-documentdb.gitdocumentdb.delete_1.md index 3cdd40be..51121e46 100644 --- a/docs-api/git-documentdb.gitdocumentdb.delete_1.md +++ b/docs-api/git-documentdb.gitdocumentdb.delete_1.md @@ -20,7 +20,7 @@ delete(jsonDoc: JsonDoc, options?: DeleteOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | Only the \_id property of the JsonDoc is referenced. \_id is a file path whose .json extension is omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | Only the \_id property of the JsonDoc is referenced. \_id is a file path whose extension is omitted. | | options | [DeleteOptions](./git-documentdb.deleteoptions.md) | | Returns: @@ -33,17 +33,17 @@ Promise<[DeleteResultJsonDoc](./git-documentdb.deleteresultjsondoc.md) > ## Exceptions -[Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) (from Collection\#delete) +[Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (from deleteImpl) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from deleteImpl) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (from deleteWorker) +\# Errors from deleteWorker -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (from deleteWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) (from deleteWorker) +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) -[Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) (from deleteWorker) +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.deletefatdoc.md b/docs-api/git-documentdb.gitdocumentdb.deletefatdoc.md index 924416c1..45bc75d7 100644 --- a/docs-api/git-documentdb.gitdocumentdb.deletefatdoc.md +++ b/docs-api/git-documentdb.gitdocumentdb.deletefatdoc.md @@ -35,15 +35,15 @@ Promise<[DeleteResult](./git-documentdb.deleteresult.md) > [Err.UndefinedDocumentIdError](./git-documentdb.err.undefineddocumentiderror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (from deleteImpl) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from deleteImpl) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (from deleteWorker) +\# Errors from deleteWorker -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (from deleteWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) (from deleteWorker) +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) -[Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) (from deleteWorker) +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.find.md b/docs-api/git-documentdb.gitdocumentdb.find.md index 6ce8f483..5b862c9b 100644 --- a/docs-api/git-documentdb.gitdocumentdb.find.md +++ b/docs-api/git-documentdb.gitdocumentdb.find.md @@ -34,7 +34,5 @@ Promise<[JsonDoc](./git-documentdb.jsondoc.md) \[\]> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.findfatdoc.md b/docs-api/git-documentdb.gitdocumentdb.findfatdoc.md index 6ac58693..6cf1d573 100644 --- a/docs-api/git-documentdb.gitdocumentdb.findfatdoc.md +++ b/docs-api/git-documentdb.gitdocumentdb.findfatdoc.md @@ -34,7 +34,5 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \[\]> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.get.md b/docs-api/git-documentdb.gitdocumentdb.get.md index 2b1b926a..71bc184b 100644 --- a/docs-api/git-documentdb.gitdocumentdb.get.md +++ b/docs-api/git-documentdb.gitdocumentdb.get.md @@ -20,7 +20,7 @@ get(_id: string): Promise; | Parameter | Type | Description | | --- | --- | --- | -| \_id | string | \_id is a file path whose .json extension is omitted. | +| \_id | string | \_id is a file path whose extension is omitted. | Returns: @@ -36,7 +36,5 @@ Promise<[JsonDoc](./git-documentdb.jsondoc.md) \| undefined> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.getcollections.md b/docs-api/git-documentdb.gitdocumentdb.getcollections.md index 88e21b75..378ec93b 100644 --- a/docs-api/git-documentdb.gitdocumentdb.getcollections.md +++ b/docs-api/git-documentdb.gitdocumentdb.getcollections.md @@ -28,7 +28,3 @@ Promise<[ICollection](./git-documentdb.icollection.md) \[\]> Promise < Collection\[\] > -## Exceptions - -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - diff --git a/docs-api/git-documentdb.gitdocumentdb.getdocbyoid.md b/docs-api/git-documentdb.gitdocumentdb.getdocbyoid.md index 0af3fa15..039cc5d5 100644 --- a/docs-api/git-documentdb.gitdocumentdb.getdocbyoid.md +++ b/docs-api/git-documentdb.gitdocumentdb.getdocbyoid.md @@ -37,7 +37,5 @@ Promise<[Doc](./git-documentdb.doc.md) \| undefined> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.getfatdoc.md b/docs-api/git-documentdb.gitdocumentdb.getfatdoc.md index 1998be6c..81b09d55 100644 --- a/docs-api/git-documentdb.gitdocumentdb.getfatdoc.md +++ b/docs-api/git-documentdb.gitdocumentdb.getfatdoc.md @@ -29,7 +29,7 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \| undefined> - undefined if a specified data does not exist. -- FatJsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. +- FatJsonDoc if the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. @@ -41,7 +41,5 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \| undefined> [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.getfatdochistory.md b/docs-api/git-documentdb.gitdocumentdb.getfatdochistory.md index 564d391f..0c62a562 100644 --- a/docs-api/git-documentdb.gitdocumentdb.getfatdochistory.md +++ b/docs-api/git-documentdb.gitdocumentdb.getfatdochistory.md @@ -30,7 +30,7 @@ Promise<([FatDoc](./git-documentdb.fatdoc.md) \| undefined)\[\]> Array of FatDoc or undefined. - undefined if a specified data does not exist or it is deleted. -- Array of FatJsonDoc if isJsonDocCollection is true or the file extension is '.json'. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. +- Array of FatJsonDoc if isJsonDocCollection is true or the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. - Array of FatBinaryDoc if described in .gitattribtues, otherwise array of FatTextDoc. @@ -46,7 +46,5 @@ Array of FatDoc or undefined. - undefined if a specified data does not exist or [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.getfatdocoldrevision.md b/docs-api/git-documentdb.gitdocumentdb.getfatdocoldrevision.md index d008dbc9..86fa1815 100644 --- a/docs-api/git-documentdb.gitdocumentdb.getfatdocoldrevision.md +++ b/docs-api/git-documentdb.gitdocumentdb.getfatdocoldrevision.md @@ -33,7 +33,7 @@ Promise<[FatDoc](./git-documentdb.fatdoc.md) \| undefined> - undefined if a specified data does not exist or it is deleted. -- JsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. +- JsonDoc if the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have \_id property when an app other than GitDocumentDB creates it. - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. @@ -54,7 +54,5 @@ db.getFatDocOldRevision(name, 2); // returns a FatDoc two revisions older than t [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.gethistory.md b/docs-api/git-documentdb.gitdocumentdb.gethistory.md index 25c90777..0895d532 100644 --- a/docs-api/git-documentdb.gitdocumentdb.gethistory.md +++ b/docs-api/git-documentdb.gitdocumentdb.gethistory.md @@ -20,7 +20,7 @@ getHistory(_id: string, historyOptions?: HistoryOptions): Promise<(JsonDoc | und | Parameter | Type | Description | | --- | --- | --- | -| \_id | string | \_id is a file path whose .json extension is omitted. | +| \_id | string | \_id is a file path whose extension is omitted. | | historyOptions | [HistoryOptions](./git-documentdb.historyoptions.md) | The array of revisions is filtered by HistoryOptions.filter. | Returns: @@ -29,7 +29,7 @@ Promise<([JsonDoc](./git-documentdb.jsondoc.md) \| undefined)\[\]> Array of FatDoc or undefined. - undefined if a specified document does not exist or it is deleted. -- JsonDoc if isJsonDocCollection is true or the file extension is '.json'. +- JsonDoc if isJsonDocCollection is true or the file extension is SerializeFormat.extension. - Uint8Array or string if isJsonDocCollection is false. @@ -77,7 +77,5 @@ Thus, a history is not [undefined, undefined, file_v2, undefined, file_v2, file_ [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.getoldrevision.md b/docs-api/git-documentdb.gitdocumentdb.getoldrevision.md index fc95e0af..eafe2517 100644 --- a/docs-api/git-documentdb.gitdocumentdb.getoldrevision.md +++ b/docs-api/git-documentdb.gitdocumentdb.getoldrevision.md @@ -20,7 +20,7 @@ getOldRevision(_id: string, revision: number, historyOptions?: HistoryOptions): | Parameter | Type | Description | | --- | --- | --- | -| \_id | string | \_id is a file path whose .json extension is omitted. | +| \_id | string | \_id is a file path whose extension is omitted. | | revision | number | Specify a number to go back to old revision. Default is 0. See [GitDocumentDB.getHistory()](./git-documentdb.gitdocumentdb.gethistory.md) for the array of revisions. | | historyOptions | [HistoryOptions](./git-documentdb.historyoptions.md) | The array of revisions is filtered by HistoryOptions.filter. | @@ -47,7 +47,5 @@ db.getOldRevision(_id, 2); // returns a document two revisions older than the la [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) - [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.insert.md b/docs-api/git-documentdb.gitdocumentdb.insert.md index 6207b30e..e20f93f6 100644 --- a/docs-api/git-documentdb.gitdocumentdb.insert.md +++ b/docs-api/git-documentdb.gitdocumentdb.insert.md @@ -20,7 +20,7 @@ insert(jsonDoc: JsonDoc, options?: PutOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and extension are omitted. | | options | [PutOptions](./git-documentdb.putoptions.md) | | Returns: @@ -33,7 +33,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - If \_id is undefined, it is automatically generated. -- The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}.json` on the file system. +- The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}${extension}` on the file system. - This is an alias of GitDocumentDB\#rootCollection.insert() @@ -41,21 +41,23 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) (from putWorker) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.insert_1.md b/docs-api/git-documentdb.gitdocumentdb.insert_1.md index 00421a62..d1a4e446 100644 --- a/docs-api/git-documentdb.gitdocumentdb.insert_1.md +++ b/docs-api/git-documentdb.gitdocumentdb.insert_1.md @@ -20,7 +20,7 @@ insert(_id: string | undefined | null, jsonDoc: JsonDoc, options?: PutOptions): | Parameter | Type | Description | | --- | --- | --- | -| \_id | string \| undefined \| null | \_id is a file path whose .json extension is omitted. | +| \_id | string \| undefined \| null | \_id is a file path whose extension is omitted. | | jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -32,7 +32,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - Throws SameIdExistsError when a document that has the same id exists. It might be better to use put() instead of insert(). -- The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. +- The saved file path is `${GitDocumentDB#workingDir}/${_id}${extension}` on the file system. - If \_id is undefined, it is automatically generated. @@ -44,21 +44,23 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) (from putWorker) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.insertfatdoc.md b/docs-api/git-documentdb.gitdocumentdb.insertfatdoc.md index 1931bcd2..41709318 100644 --- a/docs-api/git-documentdb.gitdocumentdb.insertfatdoc.md +++ b/docs-api/git-documentdb.gitdocumentdb.insertfatdoc.md @@ -32,11 +32,11 @@ Promise<[PutResult](./git-documentdb.putresult.md) > - Throws SameIdExistsError when data that has the same \_id exists. It might be better to use put() instead of insert(). -- The saved file path is `${GitDocumentDB#workingDir}/${name}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${name}extension` . - If a name parameter is undefined, it is automatically generated. -- \_id property of a JsonDoc is automatically set or overwritten by name parameter whose .json extension is omitted. +- \_id property of a JsonDoc is automatically set or overwritten by name parameter whose extension is omitted. - This is an alias of GitDocumentDB\#rootCollection.insertFatDoc() @@ -44,21 +44,23 @@ Promise<[PutResult](./git-documentdb.putresult.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) (from putWorker) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.loadappinfo.md b/docs-api/git-documentdb.gitdocumentdb.loadappinfo.md deleted file mode 100644 index 2c8aef16..00000000 --- a/docs-api/git-documentdb.gitdocumentdb.loadappinfo.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -sidebar_label: loadAppInfo() -title: GitDocumentDB.loadAppInfo() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [loadAppInfo](./git-documentdb.gitdocumentdb.loadappinfo.md) - -## GitDocumentDB.loadAppInfo() method - -Load app-specific info from .gitddb/app.json - -Signature: - -```typescript -loadAppInfo(): Promise; -``` -Returns: - -Promise<[JsonDoc](./git-documentdb.jsondoc.md) \| undefined> - -JSON object. It returns undefined if app.json does not exist. - diff --git a/docs-api/git-documentdb.gitdocumentdb.logger.md b/docs-api/git-documentdb.gitdocumentdb.logger.md index 07d83193..8f7658e0 100644 --- a/docs-api/git-documentdb.gitdocumentdb.logger.md +++ b/docs-api/git-documentdb.gitdocumentdb.logger.md @@ -13,5 +13,5 @@ Get logger Signature: ```typescript -get logger(): Logger; +get logger(): ColoredLogger; ``` diff --git a/docs-api/git-documentdb.gitdocumentdb.logtotransport.md b/docs-api/git-documentdb.gitdocumentdb.logtotransport.md new file mode 100644 index 00000000..1270d5c0 --- /dev/null +++ b/docs-api/git-documentdb.gitdocumentdb.logtotransport.md @@ -0,0 +1,17 @@ +--- +sidebar_label: logToTransport +title: GitDocumentDB.logToTransport property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [logToTransport](./git-documentdb.gitdocumentdb.logtotransport.md) + +## GitDocumentDB.logToTransport property + +logToTransport function for all log levels. See https://tslog.js.org/\#/?id=transports + +Signature: + +```typescript +get logToTransport(): ((logObject: ILogObject) => void) | undefined; +``` diff --git a/docs-api/git-documentdb.gitdocumentdb.md b/docs-api/git-documentdb.gitdocumentdb.md index 7f371183..50064485 100644 --- a/docs-api/git-documentdb.gitdocumentdb.md +++ b/docs-api/git-documentdb.gitdocumentdb.md @@ -41,11 +41,14 @@ Call open() before using DB. | [isClosing](./git-documentdb.gitdocumentdb.isclosing.md) | | boolean | DB is going to close | | [isOpened](./git-documentdb.gitdocumentdb.isopened.md) | | boolean | Test if a database is opened | | [localDir](./git-documentdb.gitdocumentdb.localdir.md) | | string | A local directory path that stores repositories of GitDocumentDB | -| [logger](./git-documentdb.gitdocumentdb.logger.md) | | Logger | Get logger | +| [logger](./git-documentdb.gitdocumentdb.logger.md) | | ColoredLogger | Get logger | | [logLevel](./git-documentdb.gitdocumentdb.loglevel.md) | | TLogLevelName | logLevel ('silly' \| 'trace' \| 'debug' \| 'info' \| 'warn' \| 'error' \| 'fatal') | +| [logToTransport](./git-documentdb.gitdocumentdb.logtotransport.md) | | ((logObject: ILogObject) => void) \| undefined | logToTransport function for all log levels. See https://tslog.js.org/\#/?id=transports | | [rootCollection](./git-documentdb.gitdocumentdb.rootcollection.md) | | [ICollection](./git-documentdb.icollection.md) | Default collection whose collectionPath is ''. | | [schema](./git-documentdb.gitdocumentdb.schema.md) | | [Schema](./git-documentdb.schema.md) | Schema for specific document type | +| [serializeFormat](./git-documentdb.gitdocumentdb.serializeformat.md) | | SerializeFormatJSON \| SerializeFormatFrontMatter | | | [taskQueue](./git-documentdb.gitdocumentdb.taskqueue.md) | | [TaskQueue](./git-documentdb.taskqueue.md) | Task queue | +| [tsLogger](./git-documentdb.gitdocumentdb.tslogger.md) | | Logger | Get logger | | [validator](./git-documentdb.gitdocumentdb.validator.md) | | [Validator](./git-documentdb.validator.md) | Name validator | | [workingDir](./git-documentdb.gitdocumentdb.workingdir.md) | | string | Get a full path of the current Git working directory | @@ -75,21 +78,18 @@ Call open() before using DB. | [insert(jsonDoc, options)](./git-documentdb.gitdocumentdb.insert.md) | | Insert a JSON document | | [insert(\_id, jsonDoc, options)](./git-documentdb.gitdocumentdb.insert_1.md) | | Insert a JSON document | | [insertFatDoc(name, doc, options)](./git-documentdb.gitdocumentdb.insertfatdoc.md) | | Insert a data | -| [loadAppInfo()](./git-documentdb.gitdocumentdb.loadappinfo.md) | | Load app-specific info from .gitddb/app.json | | [loadAuthor()](./git-documentdb.gitdocumentdb.loadauthor.md) | | Load author from .git/config | | [offSyncEvent(remoteURL, event, callback)](./git-documentdb.gitdocumentdb.offsyncevent.md) | | Remove SyncEvent handler | | [offSyncEvent(sync, event, callback)](./git-documentdb.gitdocumentdb.offsyncevent_1.md) | | Remove SyncEvent handler | | [onSyncEvent(remoteURL, event, callback)](./git-documentdb.gitdocumentdb.onsyncevent.md) | | Add SyncEvent handler | | [onSyncEvent(sync, event, callback)](./git-documentdb.gitdocumentdb.onsyncevent_1.md) | | Add SyncEvent handler | | [open(openOptions)](./git-documentdb.gitdocumentdb.open.md) | | Open or create a Git repository | +| [plugin(obj)](./git-documentdb.gitdocumentdb.plugin.md) | static | | | [put(jsonDoc, options)](./git-documentdb.gitdocumentdb.put.md) | | Insert a JSON document if not exists. Otherwise, update it. | | [put(\_id, jsonDoc, options)](./git-documentdb.gitdocumentdb.put_1.md) | | Insert a JSON document if not exists. Otherwise, update it. | | [putFatDoc(name, doc, options)](./git-documentdb.gitdocumentdb.putfatdoc.md) | | Insert data if not exists. Otherwise, update it. | | [removeSync(remoteURL)](./git-documentdb.gitdocumentdb.removesync.md) | | Stop and unregister remote synchronization | -| [repository()](./git-documentdb.gitdocumentdb.repository.md) | | Get a current repository | -| [saveAppInfo(info)](./git-documentdb.gitdocumentdb.saveappinfo.md) | | Save app-specific info into .gitddb/app.json | | [saveAuthor()](./git-documentdb.gitdocumentdb.saveauthor.md) | | Save current author to .git/config | -| [setRepository(repos)](./git-documentdb.gitdocumentdb.setrepository.md) | | Set repository | | [sync(options)](./git-documentdb.gitdocumentdb.sync.md) | | Synchronize with a remote repository | | [sync(options, getSyncResult)](./git-documentdb.gitdocumentdb.sync_1.md) | | Synchronize with a remote repository | | [update(jsonDoc, options)](./git-documentdb.gitdocumentdb.update.md) | | Update a JSON document | diff --git a/docs-api/git-documentdb.gitdocumentdb.open.md b/docs-api/git-documentdb.gitdocumentdb.open.md index 56c49c51..3db12691 100644 --- a/docs-api/git-documentdb.gitdocumentdb.open.md +++ b/docs-api/git-documentdb.gitdocumentdb.open.md @@ -40,9 +40,21 @@ Promise<[DatabaseOpenResult](./git-documentdb.databaseopenresult.md) > [Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) +[Err.RepositoryNotFoundError](./git-documentdb.err.repositorynotfounderror.md) may occurs when openOptions.createIfNotExists is false. -[Err.CannotOpenRepositoryError](./git-documentdb.err.cannotopenrepositoryerror.md) +\# Errors from \_createRepository -[Err.RepositoryNotFoundError](./git-documentdb.err.repositorynotfounderror.md) may occurs when openOptions.createIfNotExists is false. +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +\# Errors from putWorker + +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) + +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +- [Err.SameIdExistsError](./git-documentdb.err.sameidexistserror.md) + +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) + +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.plugin.md b/docs-api/git-documentdb.gitdocumentdb.plugin.md new file mode 100644 index 00000000..670a3c8e --- /dev/null +++ b/docs-api/git-documentdb.gitdocumentdb.plugin.md @@ -0,0 +1,26 @@ +--- +sidebar_label: plugin() +title: GitDocumentDB.plugin() method +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [plugin](./git-documentdb.gitdocumentdb.plugin.md) + +## GitDocumentDB.plugin() method + +Signature: + +```typescript +static plugin(obj: any): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| obj | any | | + +Returns: + +void + diff --git a/docs-api/git-documentdb.gitdocumentdb.put.md b/docs-api/git-documentdb.gitdocumentdb.put.md index 9bfb13de..da8fc7fb 100644 --- a/docs-api/git-documentdb.gitdocumentdb.put.md +++ b/docs-api/git-documentdb.gitdocumentdb.put.md @@ -20,7 +20,7 @@ put(jsonDoc: JsonDoc, options?: PutOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and extension are omitted. | | options | [PutOptions](./git-documentdb.putoptions.md) | | Returns: @@ -29,7 +29,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > ## Remarks -- The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}.json` on the file system. +- The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}${extension}` on the file system. - If \_id is undefined, it is automatically generated. @@ -39,19 +39,21 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.put_1.md b/docs-api/git-documentdb.gitdocumentdb.put_1.md index e03491cb..142aa9fa 100644 --- a/docs-api/git-documentdb.gitdocumentdb.put_1.md +++ b/docs-api/git-documentdb.gitdocumentdb.put_1.md @@ -20,7 +20,7 @@ put(_id: string | undefined | null, jsonDoc: JsonDoc, options?: PutOptions): Pro | Parameter | Type | Description | | --- | --- | --- | -| \_id | string \| undefined \| null | \_id is a file path whose .json extension is omitted. | +| \_id | string \| undefined \| null | \_id is a file path whose extension is omitted. | | jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -30,7 +30,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > ## Remarks -- The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. +- The saved file path is `${GitDocumentDB#workingDir}/${_id}${extension}` on the file system. - If \_id is undefined, it is automatically generated. @@ -44,19 +44,21 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.putfatdoc.md b/docs-api/git-documentdb.gitdocumentdb.putfatdoc.md index 6350705e..caf116d5 100644 --- a/docs-api/git-documentdb.gitdocumentdb.putfatdoc.md +++ b/docs-api/git-documentdb.gitdocumentdb.putfatdoc.md @@ -30,11 +30,11 @@ Promise<[PutResult](./git-documentdb.putresult.md) > ## Remarks -- The saved file path is `${GitDocumentDB#workingDir}/${name}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${name}extension` . - If a name parameter is undefined, it is automatically generated. -- \_id property of a JsonDoc is automatically set or overwritten by name parameter whose .json extension is removed. +- \_id property of a JsonDoc is automatically set or overwritten by name parameter whose extension is removed. - An update operation is not skipped even if no change occurred on a specified data. @@ -46,19 +46,21 @@ Promise<[PutResult](./git-documentdb.putresult.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.repository.md b/docs-api/git-documentdb.gitdocumentdb.repository.md deleted file mode 100644 index d5f97e98..00000000 --- a/docs-api/git-documentdb.gitdocumentdb.repository.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -sidebar_label: repository() -title: GitDocumentDB.repository() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [repository](./git-documentdb.gitdocumentdb.repository.md) - -## GitDocumentDB.repository() method - -> Warning: This API is now obsolete. -> -> This will be removed when NodeGit is replaced with isomorphic-git. -> - -Get a current repository - -Signature: - -```typescript -repository(): nodegit.Repository | undefined; -``` -Returns: - -nodegit.Repository \| undefined - diff --git a/docs-api/git-documentdb.gitdocumentdb.saveappinfo.md b/docs-api/git-documentdb.gitdocumentdb.saveappinfo.md deleted file mode 100644 index 31e8f420..00000000 --- a/docs-api/git-documentdb.gitdocumentdb.saveappinfo.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -sidebar_label: saveAppInfo() -title: GitDocumentDB.saveAppInfo() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [saveAppInfo](./git-documentdb.gitdocumentdb.saveappinfo.md) - -## GitDocumentDB.saveAppInfo() method - -Save app-specific info into .gitddb/app.json - -Signature: - -```typescript -saveAppInfo(info: { - [key: string]: any; - }): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| info | { \[key: string\]: any; } | | - -Returns: - -Promise<void> - diff --git a/docs-api/git-documentdb.gitdocumentdb.serializeformat.md b/docs-api/git-documentdb.gitdocumentdb.serializeformat.md new file mode 100644 index 00000000..56c4dadb --- /dev/null +++ b/docs-api/git-documentdb.gitdocumentdb.serializeformat.md @@ -0,0 +1,15 @@ +--- +sidebar_label: serializeFormat +title: GitDocumentDB.serializeFormat property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [serializeFormat](./git-documentdb.gitdocumentdb.serializeformat.md) + +## GitDocumentDB.serializeFormat property + +Signature: + +```typescript +get serializeFormat(): SerializeFormatJSON | SerializeFormatFrontMatter; +``` diff --git a/docs-api/git-documentdb.gitdocumentdb.setrepository.md b/docs-api/git-documentdb.gitdocumentdb.setrepository.md deleted file mode 100644 index d1029b0d..00000000 --- a/docs-api/git-documentdb.gitdocumentdb.setrepository.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -sidebar_label: setRepository() -title: GitDocumentDB.setRepository() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [setRepository](./git-documentdb.gitdocumentdb.setrepository.md) - -## GitDocumentDB.setRepository() method - -> Warning: This API is now obsolete. -> -> This will be removed when NodeGit is replaced with isomorphic-git. -> - -Set repository - -Signature: - -```typescript -setRepository(repos: nodegit.Repository): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| repos | nodegit.Repository | | - -Returns: - -void - -## Remarks - -Be aware that it can corrupt the database. - diff --git a/docs-api/git-documentdb.gitdocumentdb.sync.md b/docs-api/git-documentdb.gitdocumentdb.sync.md index 7d129d59..586cc03d 100644 --- a/docs-api/git-documentdb.gitdocumentdb.sync.md +++ b/docs-api/git-documentdb.gitdocumentdb.sync.md @@ -32,15 +32,13 @@ Register and synchronize with a remote repository. Do not register the same remo ## Exceptions -[Err.UndefinedRemoteURLError](./git-documentdb.err.undefinedremoteurlerror.md) (from Sync\#constructor()) +[Err.RemoteAlreadyRegisteredError](./git-documentdb.err.remotealreadyregisterederror.md) -[Err.IntervalTooSmallError](./git-documentdb.err.intervaltoosmallerror.md) (from Sync\#constructor()) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotFoundError](./git-documentdb.err.repositorynotfounderror.md) (from Sync\#syncImpl()) +[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) -[Err.RemoteRepositoryConnectError](./git-documentdb.err.remoterepositoryconnecterror.md) (from Sync\#init()) +Errors from constructor of [Sync](./git-documentdb.sync.md) class. -[Err.PushWorkerError](./git-documentdb.err.pushworkererror.md) (from Sync\#init()) - -[Err.SyncWorkerError](./git-documentdb.err.syncworkererror.md) (from Sync\#init()) +Errors from [Sync.init()](./git-documentdb.sync.init.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.sync_1.md b/docs-api/git-documentdb.gitdocumentdb.sync_1.md index 7b32a73f..4ca1cce1 100644 --- a/docs-api/git-documentdb.gitdocumentdb.sync_1.md +++ b/docs-api/git-documentdb.gitdocumentdb.sync_1.md @@ -33,15 +33,13 @@ Register and synchronize with a remote repository. Do not register the same remo ## Exceptions -[Err.UndefinedRemoteURLError](./git-documentdb.err.undefinedremoteurlerror.md) (from Sync\#constructor()) +[Err.RemoteAlreadyRegisteredError](./git-documentdb.err.remotealreadyregisterederror.md) -[Err.IntervalTooSmallError](./git-documentdb.err.intervaltoosmallerror.md) (from Sync\#constructor()) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.RepositoryNotFoundError](./git-documentdb.err.repositorynotfounderror.md) (from Sync\#syncAndGetResultImpl()) +[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) -[Err.RemoteRepositoryConnectError](./git-documentdb.err.remoterepositoryconnecterror.md) (from Sync\#init()) +Errors from constructor of [Sync](./git-documentdb.sync.md) class. -[Err.PushWorkerError](./git-documentdb.err.pushworkererror.md) (from Sync\#init()) - -[Err.SyncWorkerError](./git-documentdb.err.syncworkererror.md) (from Sync\#init()) +Errors from [Sync.init()](./git-documentdb.sync.init.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.tslogger.md b/docs-api/git-documentdb.gitdocumentdb.tslogger.md new file mode 100644 index 00000000..25375aff --- /dev/null +++ b/docs-api/git-documentdb.gitdocumentdb.tslogger.md @@ -0,0 +1,17 @@ +--- +sidebar_label: tsLogger +title: GitDocumentDB.tsLogger property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [GitDocumentDB](./git-documentdb.gitdocumentdb.md) > [tsLogger](./git-documentdb.gitdocumentdb.tslogger.md) + +## GitDocumentDB.tsLogger property + +Get logger + +Signature: + +```typescript +get tsLogger(): Logger; +``` diff --git a/docs-api/git-documentdb.gitdocumentdb.update.md b/docs-api/git-documentdb.gitdocumentdb.update.md index d3aaf992..0dacc612 100644 --- a/docs-api/git-documentdb.gitdocumentdb.update.md +++ b/docs-api/git-documentdb.gitdocumentdb.update.md @@ -20,7 +20,7 @@ update(jsonDoc: JsonDoc, options?: PutOptions): Promise; | Parameter | Type | Description | | --- | --- | --- | -| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. | +| jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | JsonDoc whose \_id is shortId. shortId is a file path whose collectionPath and extension are omitted. | | options | [PutOptions](./git-documentdb.putoptions.md) | | Returns: @@ -33,7 +33,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - If \_id is undefined, it is automatically generated. -- The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. +- The saved file path is `${GitDocumentDB#workingDir}/${_id}extension` on the file system. - This is an alias of GitDocumentDB\#rootCollection.update() @@ -41,21 +41,23 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.update_1.md b/docs-api/git-documentdb.gitdocumentdb.update_1.md index 7080efac..2ce15b13 100644 --- a/docs-api/git-documentdb.gitdocumentdb.update_1.md +++ b/docs-api/git-documentdb.gitdocumentdb.update_1.md @@ -20,7 +20,7 @@ update(_id: string | undefined | null, jsonDoc: JsonDoc, options?: PutOptions): | Parameter | Type | Description | | --- | --- | --- | -| \_id | string \| undefined \| null | \_id is a file path whose .json extension is omitted. | +| \_id | string \| undefined \| null | \_id is a file path whose extension is omitted. | | jsonDoc | [JsonDoc](./git-documentdb.jsondoc.md) | | | options | [PutOptions](./git-documentdb.putoptions.md) | | @@ -32,7 +32,7 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > - Throws DocumentNotFoundError if a specified document does not exist. It might be better to use put() instead of update(). -- The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. +- The saved file path is `${GitDocumentDB#workingDir}/${_id}extension` on the file system. - An update operation is not skipped even if no change occurred on a specified document. @@ -42,21 +42,23 @@ Promise<[PutResultJsonDoc](./git-documentdb.putresultjsondoc.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) diff --git a/docs-api/git-documentdb.gitdocumentdb.updatefatdoc.md b/docs-api/git-documentdb.gitdocumentdb.updatefatdoc.md index 12ab595a..a84dbc37 100644 --- a/docs-api/git-documentdb.gitdocumentdb.updatefatdoc.md +++ b/docs-api/git-documentdb.gitdocumentdb.updatefatdoc.md @@ -32,9 +32,9 @@ Promise<[PutResult](./git-documentdb.putresult.md) > - Throws DocumentNotFoundError if a specified data does not exist. It might be better to use put() instead of update(). -- The saved file path is `${GitDocumentDB#workingDir}/${name}.json` . +- The saved file path is `${GitDocumentDB#workingDir}/${name}extension` . -- \_id property of a JsonDoc is automatically set or overwritten by name parameter whose .json extension is omitted. +- \_id property of a JsonDoc is automatically set or overwritten by name parameter whose extension is omitted. - An update operation is not skipped even if no change occurred on a specified data. @@ -44,21 +44,23 @@ Promise<[PutResult](./git-documentdb.putresult.md) > [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) -[Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) (from validateDocument, validateId) +[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) -[Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) (from validateDocument, validateId) +[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) -[Err.DatabaseClosingError](./git-documentdb.err.databaseclosingerror.md) (fromm putImpl) +\# Errors from validateDocument, validateId -[Err.TaskCancelError](./git-documentdb.err.taskcancelerror.md) (from putImpl) +- [Err.InvalidIdCharacterError](./git-documentdb.err.invalididcharactererror.md) -[Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) (fromm putWorker) +- [Err.InvalidIdLengthError](./git-documentdb.err.invalididlengtherror.md) -[Err.RepositoryNotOpenError](./git-documentdb.err.repositorynotopenerror.md) (fromm putWorker) +\# Errors from putWorker -[Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) (from putWorker) +- [Err.UndefinedDBError](./git-documentdb.err.undefineddberror.md) -[Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) (from putWorker) +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) -[Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) +- [Err.CannotWriteDataError](./git-documentdb.err.cannotwritedataerror.md) + +- [Err.DocumentNotFoundError](./git-documentdb.err.documentnotfounderror.md) diff --git a/docs-api/git-documentdb.icollection.md b/docs-api/git-documentdb.icollection.md index 54897bc8..17bbae1b 100644 --- a/docs-api/git-documentdb.icollection.md +++ b/docs-api/git-documentdb.icollection.md @@ -17,7 +17,7 @@ export declare type ICollection = CollectionInterface & CRUDInterface & SyncEven options: CollectionOptions; collectionPath: string; parent: ICollection | undefined; - generateId(): string; + generateId(seedTime?: number): string; }; ``` References: diff --git a/docs-api/git-documentdb.json_ext.md b/docs-api/git-documentdb.json_ext.md deleted file mode 100644 index 63d92084..00000000 --- a/docs-api/git-documentdb.json_ext.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -sidebar_label: JSON_EXT variable -title: JSON_EXT variable -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [JSON\_EXT](./git-documentdb.json_ext.md) - -## JSON\_EXT variable - - -Signature: - -```typescript -JSON_EXT = ".json" -``` diff --git a/docs-api/git-documentdb.json_postfix.md b/docs-api/git-documentdb.json_postfix.md new file mode 100644 index 00000000..94f2391c --- /dev/null +++ b/docs-api/git-documentdb.json_postfix.md @@ -0,0 +1,16 @@ +--- +sidebar_label: JSON_POSTFIX variable +title: JSON_POSTFIX variable +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [JSON\_POSTFIX](./git-documentdb.json_postfix.md) + +## JSON\_POSTFIX variable + + +Signature: + +```typescript +JSON_POSTFIX = ".json" +``` diff --git a/docs-api/git-documentdb.jsondiffoptions.md b/docs-api/git-documentdb.jsondiffoptions.md deleted file mode 100644 index 598791b0..00000000 --- a/docs-api/git-documentdb.jsondiffoptions.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -sidebar_label: JsonDiffOptions type -title: JsonDiffOptions type -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [JsonDiffOptions](./git-documentdb.jsondiffoptions.md) - -## JsonDiffOptions type - -JsonDiffOptions - -Signature: - -```typescript -export declare type JsonDiffOptions = { - idOfSubtree?: string[]; - plainTextProperties?: { - [key: string]: any; - }; -}; -``` - -## Remarks - -- plainTextProperties: Only property whose key matches plainTextProperties uses text diff and patch algorithm (google-diff-match-patch). - -## Example - - -``` -e.g. -{ a: { b: true }, c: true } matches 'b' (whose ancestor is only 'a') and 'c'. -{ a: { _all: true } } matches all child properties of 'a'. -{ a: { _regex: /abc/ } } matches child properties of 'a' which match /abc/. - -``` - diff --git a/docs-api/git-documentdb.jsondiffpatchoptions.md b/docs-api/git-documentdb.jsondiffpatchoptions.md new file mode 100644 index 00000000..365214fc --- /dev/null +++ b/docs-api/git-documentdb.jsondiffpatchoptions.md @@ -0,0 +1,43 @@ +--- +sidebar_label: JsonDiffPatchOptions type +title: JsonDiffPatchOptions type +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [JsonDiffPatchOptions](./git-documentdb.jsondiffpatchoptions.md) + +## JsonDiffPatchOptions type + +JsonDiffPatchOptions + +Signature: + +```typescript +export declare type JsonDiffPatchOptions = { + keyInArrayedObject?: string[]; + keyOfUniqueArray?: string[]; + plainTextProperties?: { + [key: string]: any; + }; +}; +``` + +## Remarks + +- plainTextProperties: Only property whose key matches plainTextProperties uses text-diff-and-patch algorithm (google-diff-match-patch). + +- keyInArrayedObject: To diff between arrays that contain objects as elements, you must specify a key in the object. See https://github.com/benjamine/jsondiffpatch/blob/master/docs/arrays.md\#an-object-hash + +- keyOfUniqueArray: Set a key of a unique array. Unique array never include duplicated members after JSON patch. + +## Example + + +``` +Example of plainTextProperties: +{ a: { b: true }, c: true } matches 'b' (whose ancestor is only 'a') and 'c'. +{ a: { _all: true } } matches all child properties of 'a'. +{ a: { _regex: /abc/ } } matches child properties of 'a' which match /abc/. + +``` + diff --git a/docs-api/git-documentdb.jsondocmetadata.md b/docs-api/git-documentdb.jsondocmetadata.md index c9bfa3fd..23a9629f 100644 --- a/docs-api/git-documentdb.jsondocmetadata.md +++ b/docs-api/git-documentdb.jsondocmetadata.md @@ -23,9 +23,9 @@ export declare type JsonDocMetadata = { ## Remarks -- \_id: \_id of a JSON document. This is a file name without .json extension. +- \_id: \_id of a JSON document. This is a file name without extension. -- name: A file name in Git. e.g.) "foo.json", "bar/baz.json" +- name: A file name in Git. e.g.) "foo.json", "bar/baz.md" - fileOid: SHA-1 hash of Git object (40 characters) diff --git a/docs-api/git-documentdb.md b/docs-api/git-documentdb.md index 50595f9c..4d8e6ab7 100644 --- a/docs-api/git-documentdb.md +++ b/docs-api/git-documentdb.md @@ -21,6 +21,12 @@ Offline-first Database that Syncs with Git | [TaskQueue](./git-documentdb.taskqueue.md) | TaskQueue | | [Validator](./git-documentdb.validator.md) | Validator Class | +## Functions + +| Function | Description | +| --- | --- | +| [encodeToGitRemoteName(remoteURL)](./git-documentdb.encodetogitremotename.md) | encodeToGitRemoteName | + ## Interfaces | Interface | Description | @@ -36,6 +42,7 @@ Offline-first Database that Syncs with Git | Namespace | Description | | --- | --- | | [Err](./git-documentdb.err.md) | Namespace for errors | +| [RemoteErr](./git-documentdb.remoteerr.md) | RemoteError | ## Variables @@ -49,20 +56,23 @@ Offline-first Database that Syncs with Git | [DEFAULT\_LOG\_LEVEL](./git-documentdb.default_log_level.md) | | | [DEFAULT\_SYNC\_INTERVAL](./git-documentdb.default_sync_interval.md) | | | [DUPLICATED\_FILE\_POSTFIX](./git-documentdb.duplicated_file_postfix.md) | | +| [FILE\_CREATE\_TIMEOUT](./git-documentdb.file_create_timeout.md) | | | [FILE\_REMOVE\_TIMEOUT](./git-documentdb.file_remove_timeout.md) | | | [FIRST\_COMMIT\_MESSAGE](./git-documentdb.first_commit_message.md) | | -| [GIT\_DOCUMENTDB\_APP\_INFO\_ID](./git-documentdb.git_documentdb_app_info_id.md) | | +| [FRONT\_MATTER\_POSTFIX](./git-documentdb.front_matter_postfix.md) | | | [GIT\_DOCUMENTDB\_INFO\_ID](./git-documentdb.git_documentdb_info_id.md) | | | [GIT\_DOCUMENTDB\_METADATA\_DIR](./git-documentdb.git_documentdb_metadata_dir.md) | | -| [JSON\_EXT](./git-documentdb.json_ext.md) | | +| [JSON\_POSTFIX](./git-documentdb.json_postfix.md) | | | [MAX\_FILE\_PATH\_LENGTH](./git-documentdb.max_file_path_length.md) | | | [MINIMUM\_SYNC\_INTERVAL](./git-documentdb.minimum_sync_interval.md) | | | [NETWORK\_RETRY\_INTERVAL](./git-documentdb.network_retry_interval.md) | | | [NETWORK\_RETRY](./git-documentdb.network_retry.md) | | | [NETWORK\_TIMEOUT](./git-documentdb.network_timeout.md) | | | [PUT\_APP\_INFO\_MESSAGE](./git-documentdb.put_app_info_message.md) | | +| [RemoteEngine](./git-documentdb.remoteengine.md) | RemoteEngine | | [SET\_DATABASE\_ID\_MESSAGE](./git-documentdb.set_database_id_message.md) | | | [SHORT\_SHA\_LENGTH](./git-documentdb.short_sha_length.md) | | +| [YAML\_POSTFIX](./git-documentdb.yaml_postfix.md) | | ## Type Aliases @@ -105,11 +115,12 @@ Offline-first Database that Syncs with Git | [HistoryFilter](./git-documentdb.historyfilter.md) | Filter for file history | | [HistoryOptions](./git-documentdb.historyoptions.md) | Options for getHistory() and getFatDocHistory() | | [ICollection](./git-documentdb.icollection.md) | Type for Collection Class | -| [JsonDiffOptions](./git-documentdb.jsondiffoptions.md) | JsonDiffOptions | +| [JsonDiffPatchOptions](./git-documentdb.jsondiffpatchoptions.md) | JsonDiffPatchOptions | | [JsonDoc](./git-documentdb.jsondoc.md) | The type for a JSON document that is stored in a database | | [JsonDocMetadata](./git-documentdb.jsondocmetadata.md) | Metadata for JsonDoc | | [NormalizedCommit](./git-documentdb.normalizedcommit.md) | Normalized Commit | | [OpenOptions](./git-documentdb.openoptions.md) | Database open options | +| [PluginTypes](./git-documentdb.plugintypes.md) | Plugin types | | [PutOptions](./git-documentdb.putoptions.md) | Options for put APIs (put, update, insert, putFatDoc, updateFatDoc, and insertFatDoc) | | [PutResult](./git-documentdb.putresult.md) | Result of put APIs (put, update, insert, putFatDoc, updateFatDoc, and insertFatDoc) | | [PutResultBinary](./git-documentdb.putresultbinary.md) | | @@ -117,6 +128,7 @@ Offline-first Database that Syncs with Git | [PutResultText](./git-documentdb.putresulttext.md) | | | [RemoteOptions](./git-documentdb.remoteoptions.md) | Options for Sync class | | [Schema](./git-documentdb.schema.md) | Schema for specific document type | +| [SerializeFormatLabel](./git-documentdb.serializeformatlabel.md) | Format for serialization | | [SyncCallback](./git-documentdb.synccallback.md) | Union type of SyncEventCallbacks | | [SyncChangeCallback](./git-documentdb.syncchangecallback.md) | Callback of 'change' event | | [SyncCombineDatabaseCallback](./git-documentdb.synccombinedatabasecallback.md) | Callback of 'combine' event | diff --git a/docs-api/git-documentdb.plugintypes.md b/docs-api/git-documentdb.plugintypes.md new file mode 100644 index 00000000..f93689fd --- /dev/null +++ b/docs-api/git-documentdb.plugintypes.md @@ -0,0 +1,17 @@ +--- +sidebar_label: PluginTypes type +title: PluginTypes type +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [PluginTypes](./git-documentdb.plugintypes.md) + +## PluginTypes type + +Plugin types + +Signature: + +```typescript +export declare type PluginTypes = 'db' | 'remote'; +``` diff --git a/docs-api/git-documentdb.putoptions.md b/docs-api/git-documentdb.putoptions.md index 0d39c64d..a28617cb 100644 --- a/docs-api/git-documentdb.putoptions.md +++ b/docs-api/git-documentdb.putoptions.md @@ -18,6 +18,7 @@ export declare type PutOptions = { insertOrUpdate?: 'insert' | 'update'; taskId?: string; enqueueCallback?: (taskMetadata: TaskMetadata) => void; + debounceTime?: number; }; ``` References: @@ -34,3 +35,5 @@ export declare type PutOptions = { - enqueueCallback: A callback function called just after this put task is enqueued to TaskQueue. +- debounceTime: put/insert/update operations for the same document are debounced by specified milliseconds. This overwrite the same option in Collection Class. Default is -1 (do not debounce). + diff --git a/docs-api/git-documentdb.putresult.md b/docs-api/git-documentdb.putresult.md index 181cc9ad..b09223d8 100644 --- a/docs-api/git-documentdb.putresult.md +++ b/docs-api/git-documentdb.putresult.md @@ -21,7 +21,7 @@ export declare type PutResult = PutResultJsonDoc | PutResultText | PutResultBina ## Remarks -- \_id: \_id of a JSON document. This is a file name without .json extension. PutResult does not have \_id if a document is not [JsonDoc](./git-documentdb.jsondoc.md) type. +- \_id: \_id of a JSON document. This is a file name without extension. PutResult does not have \_id if a document is not [JsonDoc](./git-documentdb.jsondoc.md) type. - name: A file name in Git. e.g.) "foo.json", "bar/baz.md" diff --git a/docs-api/git-documentdb.remoteengine.md b/docs-api/git-documentdb.remoteengine.md new file mode 100644 index 00000000..30f6b209 --- /dev/null +++ b/docs-api/git-documentdb.remoteengine.md @@ -0,0 +1,19 @@ +--- +sidebar_label: RemoteEngine variable +title: RemoteEngine variable +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteEngine](./git-documentdb.remoteengine.md) + +## RemoteEngine variable + +RemoteEngine + +Signature: + +```typescript +RemoteEngine: { + [key: string]: RemoteEngineInterface; +} +``` diff --git a/docs-api/git-documentdb.remoteerr.cannotconnecterror._constructor_.md b/docs-api/git-documentdb.remoteerr.cannotconnecterror._constructor_.md new file mode 100644 index 00000000..64b5618d --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.cannotconnecterror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.CannotConnectError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [CannotConnectError](./git-documentdb.remoteerr.cannotconnecterror.md) > [(constructor)](./git-documentdb.remoteerr.cannotconnecterror._constructor_.md) + +## RemoteErr.CannotConnectError.(constructor) + +Constructs a new instance of the `CannotConnectError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.cannotconnecterror.md b/docs-api/git-documentdb.remoteerr.cannotconnecterror.md new file mode 100644 index 00000000..b9b27d3f --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.cannotconnecterror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: CannotConnectError +title: RemoteErr.CannotConnectError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [CannotConnectError](./git-documentdb.remoteerr.cannotconnecterror.md) + +## RemoteErr.CannotConnectError class + +Signature: + +```typescript +class CannotConnectError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.cannotconnecterror._constructor_.md) | | Constructs a new instance of the CannotConnectError class | + diff --git a/docs-api/git-documentdb.remoteerr.httperror401authorizationrequired._constructor_.md b/docs-api/git-documentdb.remoteerr.httperror401authorizationrequired._constructor_.md new file mode 100644 index 00000000..6ad8e9e2 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.httperror401authorizationrequired._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.HTTPError401AuthorizationRequired.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [HTTPError401AuthorizationRequired](./git-documentdb.remoteerr.httperror401authorizationrequired.md) > [(constructor)](./git-documentdb.remoteerr.httperror401authorizationrequired._constructor_.md) + +## RemoteErr.HTTPError401AuthorizationRequired.(constructor) + +Constructs a new instance of the `HTTPError401AuthorizationRequired` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.httperror401authorizationrequired.md b/docs-api/git-documentdb.remoteerr.httperror401authorizationrequired.md new file mode 100644 index 00000000..0b095aee --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.httperror401authorizationrequired.md @@ -0,0 +1,25 @@ +--- +sidebar_label: HTTPError401AuthorizationRequired +title: RemoteErr.HTTPError401AuthorizationRequired class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [HTTPError401AuthorizationRequired](./git-documentdb.remoteerr.httperror401authorizationrequired.md) + +## RemoteErr.HTTPError401AuthorizationRequired class + +Signature: + +```typescript +class HTTPError401AuthorizationRequired extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.httperror401authorizationrequired._constructor_.md) | | Constructs a new instance of the HTTPError401AuthorizationRequired class | + diff --git a/docs-api/git-documentdb.remoteerr.httperror403forbidden._constructor_.md b/docs-api/git-documentdb.remoteerr.httperror403forbidden._constructor_.md new file mode 100644 index 00000000..9ada4440 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.httperror403forbidden._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.HTTPError403Forbidden.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [HTTPError403Forbidden](./git-documentdb.remoteerr.httperror403forbidden.md) > [(constructor)](./git-documentdb.remoteerr.httperror403forbidden._constructor_.md) + +## RemoteErr.HTTPError403Forbidden.(constructor) + +Constructs a new instance of the `HTTPError403Forbidden` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.httperror403forbidden.md b/docs-api/git-documentdb.remoteerr.httperror403forbidden.md new file mode 100644 index 00000000..4f2db8e7 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.httperror403forbidden.md @@ -0,0 +1,25 @@ +--- +sidebar_label: HTTPError403Forbidden +title: RemoteErr.HTTPError403Forbidden class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [HTTPError403Forbidden](./git-documentdb.remoteerr.httperror403forbidden.md) + +## RemoteErr.HTTPError403Forbidden class + +Signature: + +```typescript +class HTTPError403Forbidden extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.httperror403forbidden._constructor_.md) | | Constructs a new instance of the HTTPError403Forbidden class | + diff --git a/docs-api/git-documentdb.remoteerr.httperror404notfound._constructor_.md b/docs-api/git-documentdb.remoteerr.httperror404notfound._constructor_.md new file mode 100644 index 00000000..e552baf6 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.httperror404notfound._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.HTTPError404NotFound.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [HTTPError404NotFound](./git-documentdb.remoteerr.httperror404notfound.md) > [(constructor)](./git-documentdb.remoteerr.httperror404notfound._constructor_.md) + +## RemoteErr.HTTPError404NotFound.(constructor) + +Constructs a new instance of the `HTTPError404NotFound` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.httperror404notfound.md b/docs-api/git-documentdb.remoteerr.httperror404notfound.md new file mode 100644 index 00000000..ab4acffb --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.httperror404notfound.md @@ -0,0 +1,25 @@ +--- +sidebar_label: HTTPError404NotFound +title: RemoteErr.HTTPError404NotFound class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [HTTPError404NotFound](./git-documentdb.remoteerr.httperror404notfound.md) + +## RemoteErr.HTTPError404NotFound class + +Signature: + +```typescript +class HTTPError404NotFound extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.httperror404notfound._constructor_.md) | | Constructs a new instance of the HTTPError404NotFound class | + diff --git a/docs-api/git-documentdb.remoteerr.invalidauthenticationtypeerror._constructor_.md b/docs-api/git-documentdb.remoteerr.invalidauthenticationtypeerror._constructor_.md new file mode 100644 index 00000000..5a0c1d7a --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidauthenticationtypeerror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.InvalidAuthenticationTypeError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidAuthenticationTypeError](./git-documentdb.remoteerr.invalidauthenticationtypeerror.md) > [(constructor)](./git-documentdb.remoteerr.invalidauthenticationtypeerror._constructor_.md) + +## RemoteErr.InvalidAuthenticationTypeError.(constructor) + +Constructs a new instance of the `InvalidAuthenticationTypeError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.invalidauthenticationtypeerror.md b/docs-api/git-documentdb.remoteerr.invalidauthenticationtypeerror.md new file mode 100644 index 00000000..3aaa6830 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidauthenticationtypeerror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: InvalidAuthenticationTypeError +title: RemoteErr.InvalidAuthenticationTypeError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidAuthenticationTypeError](./git-documentdb.remoteerr.invalidauthenticationtypeerror.md) + +## RemoteErr.InvalidAuthenticationTypeError class + +Signature: + +```typescript +class InvalidAuthenticationTypeError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.invalidauthenticationtypeerror._constructor_.md) | | Constructs a new instance of the InvalidAuthenticationTypeError class | + diff --git a/docs-api/git-documentdb.remoteerr.invalidgitremoteerror._constructor_.md b/docs-api/git-documentdb.remoteerr.invalidgitremoteerror._constructor_.md new file mode 100644 index 00000000..c64af94d --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidgitremoteerror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.InvalidGitRemoteError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidGitRemoteError](./git-documentdb.remoteerr.invalidgitremoteerror.md) > [(constructor)](./git-documentdb.remoteerr.invalidgitremoteerror._constructor_.md) + +## RemoteErr.InvalidGitRemoteError.(constructor) + +Constructs a new instance of the `InvalidGitRemoteError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.invalidgitremoteerror.md b/docs-api/git-documentdb.remoteerr.invalidgitremoteerror.md new file mode 100644 index 00000000..f180cbc1 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidgitremoteerror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: InvalidGitRemoteError +title: RemoteErr.InvalidGitRemoteError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidGitRemoteError](./git-documentdb.remoteerr.invalidgitremoteerror.md) + +## RemoteErr.InvalidGitRemoteError class + +Signature: + +```typescript +class InvalidGitRemoteError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.invalidgitremoteerror._constructor_.md) | | Constructs a new instance of the InvalidGitRemoteError class | + diff --git a/docs-api/git-documentdb.remoteerr.invalidrepositoryurlerror._constructor_.md b/docs-api/git-documentdb.remoteerr.invalidrepositoryurlerror._constructor_.md new file mode 100644 index 00000000..91973c60 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidrepositoryurlerror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.InvalidRepositoryURLError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidRepositoryURLError](./git-documentdb.remoteerr.invalidrepositoryurlerror.md) > [(constructor)](./git-documentdb.remoteerr.invalidrepositoryurlerror._constructor_.md) + +## RemoteErr.InvalidRepositoryURLError.(constructor) + +Constructs a new instance of the `InvalidRepositoryURLError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.invalidrepositoryurlerror.md b/docs-api/git-documentdb.remoteerr.invalidrepositoryurlerror.md new file mode 100644 index 00000000..3c09021a --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidrepositoryurlerror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: InvalidRepositoryURLError +title: RemoteErr.InvalidRepositoryURLError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidRepositoryURLError](./git-documentdb.remoteerr.invalidrepositoryurlerror.md) + +## RemoteErr.InvalidRepositoryURLError class + +Signature: + +```typescript +class InvalidRepositoryURLError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.invalidrepositoryurlerror._constructor_.md) | | Constructs a new instance of the InvalidRepositoryURLError class | + diff --git a/docs-api/git-documentdb.remoteerr.invalidsshkeypatherror._constructor_.md b/docs-api/git-documentdb.remoteerr.invalidsshkeypatherror._constructor_.md new file mode 100644 index 00000000..d2acbe2b --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidsshkeypatherror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.InvalidSSHKeyPathError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidSSHKeyPathError](./git-documentdb.remoteerr.invalidsshkeypatherror.md) > [(constructor)](./git-documentdb.remoteerr.invalidsshkeypatherror._constructor_.md) + +## RemoteErr.InvalidSSHKeyPathError.(constructor) + +Constructs a new instance of the `InvalidSSHKeyPathError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.invalidsshkeypatherror.md b/docs-api/git-documentdb.remoteerr.invalidsshkeypatherror.md new file mode 100644 index 00000000..6de84175 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidsshkeypatherror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: InvalidSSHKeyPathError +title: RemoteErr.InvalidSSHKeyPathError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidSSHKeyPathError](./git-documentdb.remoteerr.invalidsshkeypatherror.md) + +## RemoteErr.InvalidSSHKeyPathError class + +Signature: + +```typescript +class InvalidSSHKeyPathError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.invalidsshkeypatherror._constructor_.md) | | Constructs a new instance of the InvalidSSHKeyPathError class | + diff --git a/docs-api/git-documentdb.remoteerr.invalidurlformaterror._constructor_.md b/docs-api/git-documentdb.remoteerr.invalidurlformaterror._constructor_.md new file mode 100644 index 00000000..40884b5a --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidurlformaterror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.InvalidURLFormatError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) > [(constructor)](./git-documentdb.remoteerr.invalidurlformaterror._constructor_.md) + +## RemoteErr.InvalidURLFormatError.(constructor) + +Constructs a new instance of the `InvalidURLFormatError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.invalidurlformaterror.md b/docs-api/git-documentdb.remoteerr.invalidurlformaterror.md new file mode 100644 index 00000000..28b3322e --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.invalidurlformaterror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: InvalidURLFormatError +title: RemoteErr.InvalidURLFormatError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + +## RemoteErr.InvalidURLFormatError class + +Signature: + +```typescript +class InvalidURLFormatError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.invalidurlformaterror._constructor_.md) | | Constructs a new instance of the InvalidURLFormatError class | + diff --git a/docs-api/git-documentdb.remoteerr.md b/docs-api/git-documentdb.remoteerr.md new file mode 100644 index 00000000..3d8364b4 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.md @@ -0,0 +1,34 @@ +--- +sidebar_label: RemoteErr namespace +title: RemoteErr namespace +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) + +## RemoteErr namespace + +RemoteError + +Signature: + +```typescript +export declare namespace RemoteErr +``` + +## Classes + +| Class | Description | +| --- | --- | +| [CannotConnectError](./git-documentdb.remoteerr.cannotconnecterror.md) | | +| [HTTPError401AuthorizationRequired](./git-documentdb.remoteerr.httperror401authorizationrequired.md) | | +| [HTTPError403Forbidden](./git-documentdb.remoteerr.httperror403forbidden.md) | | +| [HTTPError404NotFound](./git-documentdb.remoteerr.httperror404notfound.md) | | +| [InvalidAuthenticationTypeError](./git-documentdb.remoteerr.invalidauthenticationtypeerror.md) | | +| [InvalidGitRemoteError](./git-documentdb.remoteerr.invalidgitremoteerror.md) | | +| [InvalidRepositoryURLError](./git-documentdb.remoteerr.invalidrepositoryurlerror.md) | | +| [InvalidSSHKeyPathError](./git-documentdb.remoteerr.invalidsshkeypatherror.md) | | +| [InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) | | +| [NetworkError](./git-documentdb.remoteerr.networkerror.md) | | +| [UnfetchedCommitExistsError](./git-documentdb.remoteerr.unfetchedcommitexistserror.md) | | + diff --git a/docs-api/git-documentdb.remoteerr.networkerror._constructor_.md b/docs-api/git-documentdb.remoteerr.networkerror._constructor_.md new file mode 100644 index 00000000..657aa689 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.networkerror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.NetworkError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [NetworkError](./git-documentdb.remoteerr.networkerror.md) > [(constructor)](./git-documentdb.remoteerr.networkerror._constructor_.md) + +## RemoteErr.NetworkError.(constructor) + +Constructs a new instance of the `NetworkError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.networkerror.md b/docs-api/git-documentdb.remoteerr.networkerror.md new file mode 100644 index 00000000..01d853c6 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.networkerror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: NetworkError +title: RemoteErr.NetworkError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [NetworkError](./git-documentdb.remoteerr.networkerror.md) + +## RemoteErr.NetworkError class + +Signature: + +```typescript +class NetworkError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.networkerror._constructor_.md) | | Constructs a new instance of the NetworkError class | + diff --git a/docs-api/git-documentdb.remoteerr.unfetchedcommitexistserror._constructor_.md b/docs-api/git-documentdb.remoteerr.unfetchedcommitexistserror._constructor_.md new file mode 100644 index 00000000..c8abc816 --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.unfetchedcommitexistserror._constructor_.md @@ -0,0 +1,24 @@ +--- +sidebar_label: (constructor) +title: RemoteErr.UnfetchedCommitExistsError.(constructor) +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [UnfetchedCommitExistsError](./git-documentdb.remoteerr.unfetchedcommitexistserror.md) > [(constructor)](./git-documentdb.remoteerr.unfetchedcommitexistserror._constructor_.md) + +## RemoteErr.UnfetchedCommitExistsError.(constructor) + +Constructs a new instance of the `UnfetchedCommitExistsError` class + +Signature: + +```typescript +constructor(mes: unknown); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mes | unknown | | + diff --git a/docs-api/git-documentdb.remoteerr.unfetchedcommitexistserror.md b/docs-api/git-documentdb.remoteerr.unfetchedcommitexistserror.md new file mode 100644 index 00000000..ffabc15a --- /dev/null +++ b/docs-api/git-documentdb.remoteerr.unfetchedcommitexistserror.md @@ -0,0 +1,25 @@ +--- +sidebar_label: UnfetchedCommitExistsError +title: RemoteErr.UnfetchedCommitExistsError class +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteErr](./git-documentdb.remoteerr.md) > [UnfetchedCommitExistsError](./git-documentdb.remoteerr.unfetchedcommitexistserror.md) + +## RemoteErr.UnfetchedCommitExistsError class + +Signature: + +```typescript +class UnfetchedCommitExistsError extends BaseError +``` +Extends: + +BaseError + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(mes)](./git-documentdb.remoteerr.unfetchedcommitexistserror._constructor_.md) | | Constructs a new instance of the UnfetchedCommitExistsError class | + diff --git a/docs-api/git-documentdb.remoterepository._constructor_.md b/docs-api/git-documentdb.remoterepository._constructor_.md index 7074125b..0f040a7b 100644 --- a/docs-api/git-documentdb.remoterepository._constructor_.md +++ b/docs-api/git-documentdb.remoterepository._constructor_.md @@ -22,7 +22,3 @@ constructor(options: RemoteOptions); | --- | --- | --- | | options | [RemoteOptions](./git-documentdb.remoteoptions.md) | | -## Exceptions - -[Err.InvalidAuthenticationTypeError](./git-documentdb.err.invalidauthenticationtypeerror.md) - diff --git a/docs-api/git-documentdb.remoterepository.connect.md b/docs-api/git-documentdb.remoterepository.connect.md deleted file mode 100644 index 1a1426ab..00000000 --- a/docs-api/git-documentdb.remoterepository.connect.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -sidebar_label: connect() -title: RemoteRepository.connect() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [RemoteRepository](./git-documentdb.remoterepository.md) > [connect](./git-documentdb.remoterepository.connect.md) - -## RemoteRepository.connect() method - -Set a remote repository and connect to the remote repository. A remote repository will be created if not exists. - -Signature: - -```typescript -connect(repos: nodegit.Repository, credentialCallbacks: { - [key: string]: any; - }, onlyFetch?: boolean): Promise<[GitRemoteAction, 'exist' | 'create']>; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| repos | nodegit.Repository | | -| credentialCallbacks | { \[key: string\]: any; } | | -| onlyFetch | boolean | | - -Returns: - -Promise<\[GitRemoteAction, 'exist' \| 'create'\]> - -## Exceptions - -[Err.UndefinedPersonalAccessTokenError](./git-documentdb.err.undefinedpersonalaccesstokenerror.md) (from RemoteRepository\#create()) - -[Err.PersonalAccessTokenForAnotherAccountError](./git-documentdb.err.personalaccesstokenforanotheraccounterror.md) (from RemoteRepository\#create()) - -[Err.CannotConnectError](./git-documentdb.err.cannotconnecterror.md) (from RemoteRepository\#create()) - -[Err.AuthenticationTypeNotAllowCreateRepositoryError](./git-documentdb.err.authenticationtypenotallowcreaterepositoryerror.md) (from RemoteRepository\#create()) - -[Err.FetchConnectionFailedError](./git-documentdb.err.fetchconnectionfailederror.md) - -[Err.CannotCreateRemoteRepositoryError](./git-documentdb.err.cannotcreateremoterepositoryerror.md) - -[Err.PushConnectionFailedError](./git-documentdb.err.pushconnectionfailederror.md) - diff --git a/docs-api/git-documentdb.remoterepository.create.md b/docs-api/git-documentdb.remoterepository.create.md index 09b32b57..6e38d19d 100644 --- a/docs-api/git-documentdb.remoterepository.create.md +++ b/docs-api/git-documentdb.remoterepository.create.md @@ -29,7 +29,7 @@ connection.type must be 'github' [Err.PersonalAccessTokenForAnotherAccountError](./git-documentdb.err.personalaccesstokenforanotheraccounterror.md) -[Err.CannotConnectError](./git-documentdb.err.cannotconnecterror.md) +[Err.CannotConnectRemoteRepositoryError](./git-documentdb.err.cannotconnectremoterepositoryerror.md) may include the following errors: diff --git a/docs-api/git-documentdb.remoterepository.destroy.md b/docs-api/git-documentdb.remoterepository.destroy.md index a058f5cf..070679a2 100644 --- a/docs-api/git-documentdb.remoterepository.destroy.md +++ b/docs-api/git-documentdb.remoterepository.destroy.md @@ -27,7 +27,7 @@ connection.type must be 'github' [Err.UndefinedPersonalAccessTokenError](./git-documentdb.err.undefinedpersonalaccesstokenerror.md) -[Err.CannotConnectError](./git-documentdb.err.cannotconnecterror.md) +[Err.CannotConnectRemoteRepositoryError](./git-documentdb.err.cannotconnectremoterepositoryerror.md) may include the following errors: diff --git a/docs-api/git-documentdb.remoterepository.md b/docs-api/git-documentdb.remoterepository.md index ebc1d9fb..934d6b26 100644 --- a/docs-api/git-documentdb.remoterepository.md +++ b/docs-api/git-documentdb.remoterepository.md @@ -26,7 +26,6 @@ export declare class RemoteRepository | Method | Modifiers | Description | | --- | --- | --- | -| [connect(repos, credentialCallbacks, onlyFetch)](./git-documentdb.remoterepository.connect.md) | | Set a remote repository and connect to the remote repository. A remote repository will be created if not exists. | | [create()](./git-documentdb.remoterepository.create.md) | | Create a repository on a remote site | | [destroy()](./git-documentdb.remoterepository.destroy.md) | | Delete a repository on a remote site | diff --git a/docs-api/git-documentdb.schema.md b/docs-api/git-documentdb.schema.md index afc52562..8d80f0b7 100644 --- a/docs-api/git-documentdb.schema.md +++ b/docs-api/git-documentdb.schema.md @@ -14,10 +14,10 @@ Schema for specific document type ```typescript export declare type Schema = { - json: JsonDiffOptions; + json: JsonDiffPatchOptions; }; ``` References: -[JsonDiffOptions](./git-documentdb.jsondiffoptions.md) +[JsonDiffPatchOptions](./git-documentdb.jsondiffpatchoptions.md) diff --git a/docs-api/git-documentdb.serializeformatlabel.md b/docs-api/git-documentdb.serializeformatlabel.md new file mode 100644 index 00000000..2aaaf4f1 --- /dev/null +++ b/docs-api/git-documentdb.serializeformatlabel.md @@ -0,0 +1,17 @@ +--- +sidebar_label: SerializeFormatLabel type +title: SerializeFormatLabel type +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SerializeFormatLabel](./git-documentdb.serializeformatlabel.md) + +## SerializeFormatLabel type + +Format for serialization + +Signature: + +```typescript +export declare type SerializeFormatLabel = 'json' | 'front-matter'; +``` diff --git a/docs-api/git-documentdb.sync._constructor_.md b/docs-api/git-documentdb.sync._constructor_.md index 0c22366f..366280c6 100644 --- a/docs-api/git-documentdb.sync._constructor_.md +++ b/docs-api/git-documentdb.sync._constructor_.md @@ -29,5 +29,9 @@ constructor(gitDDB: GitDDBInterface, options?: RemoteOptions); [Err.IntervalTooSmallError](./git-documentdb.err.intervaltoosmallerror.md) -[Err.InvalidAuthenticationTypeError](./git-documentdb.err.invalidauthenticationtypeerror.md) +[Err.SyncIntervalLessThanOrEqualToRetryIntervalError](./git-documentdb.err.syncintervallessthanorequaltoretryintervalerror.md) + +\# Errors from encodeToGitRemoteName + +- [RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) diff --git a/docs-api/git-documentdb.sync.credentialcallbacks.md b/docs-api/git-documentdb.sync.credentialcallbacks.md deleted file mode 100644 index 52d04f21..00000000 --- a/docs-api/git-documentdb.sync.credentialcallbacks.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_label: credentialCallbacks -title: Sync.credentialCallbacks property -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Sync](./git-documentdb.sync.md) > [credentialCallbacks](./git-documentdb.sync.credentialcallbacks.md) - -## Sync.credentialCallbacks property - -Callback for authentication - -Signature: - -```typescript -credentialCallbacks: { - [key: string]: any; - }; -``` diff --git a/docs-api/git-documentdb.sync.engine.md b/docs-api/git-documentdb.sync.engine.md new file mode 100644 index 00000000..9704041c --- /dev/null +++ b/docs-api/git-documentdb.sync.engine.md @@ -0,0 +1,15 @@ +--- +sidebar_label: engine +title: Sync.engine property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Sync](./git-documentdb.sync.md) > [engine](./git-documentdb.sync.engine.md) + +## Sync.engine property + +Signature: + +```typescript +get engine(): string; +``` diff --git a/docs-api/git-documentdb.sync.enqueuepushtask.md b/docs-api/git-documentdb.sync.enqueuepushtask.md deleted file mode 100644 index f4077756..00000000 --- a/docs-api/git-documentdb.sync.enqueuepushtask.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -sidebar_label: enqueuePushTask() -title: Sync.enqueuePushTask() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Sync](./git-documentdb.sync.md) > [enqueuePushTask](./git-documentdb.sync.enqueuepushtask.md) - -## Sync.enqueuePushTask() method - -Enqueue push task to TaskQueue - -Signature: - -```typescript -enqueuePushTask(): Promise; -``` -Returns: - -Promise<[SyncResultPush](./git-documentdb.syncresultpush.md) \| [SyncResultCancel](./git-documentdb.syncresultcancel.md) > - -## Exceptions - -[Err.PushWorkerError](./git-documentdb.err.pushworkererror.md) - -[Err.UnfetchedCommitExistsError](./git-documentdb.err.unfetchedcommitexistserror.md) - -[Err.PushNotAllowedError](./git-documentdb.err.pushnotallowederror.md) - diff --git a/docs-api/git-documentdb.sync.enqueuesynctask.md b/docs-api/git-documentdb.sync.enqueuesynctask.md index 55f83511..3879e4b6 100644 --- a/docs-api/git-documentdb.sync.enqueuesynctask.md +++ b/docs-api/git-documentdb.sync.enqueuesynctask.md @@ -13,19 +13,16 @@ Enqueue sync task to TaskQueue Signature: ```typescript -enqueueSyncTask(): Promise; +enqueueSyncTask(calledAsPeriodicTask: boolean): Promise; ``` -Returns: - -Promise<[SyncResult](./git-documentdb.syncresult.md) > -## Exceptions +## Parameters -[Err.SyncWorkerError](./git-documentdb.err.syncworkererror.md) +| Parameter | Type | Description | +| --- | --- | --- | +| calledAsPeriodicTask | boolean | | -[Err.NoMergeBaseFoundError](./git-documentdb.err.nomergebasefounderror.md) - -[Err.UnfetchedCommitExistsError](./git-documentdb.err.unfetchedcommitexistserror.md) +Returns: -[Err.PushNotAllowedError](./git-documentdb.err.pushnotallowederror.md) +Promise<[SyncResult](./git-documentdb.syncresult.md) > diff --git a/docs-api/git-documentdb.sync.init.md b/docs-api/git-documentdb.sync.init.md index 04bfc429..07e78d3e 100644 --- a/docs-api/git-documentdb.sync.init.md +++ b/docs-api/git-documentdb.sync.init.md @@ -8,20 +8,13 @@ hide_title: true ## Sync.init() method -Create remote connection +Initialize remote connection Signature: ```typescript -init(repos: nodegit.Repository): Promise; +init(): Promise; ``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| repos | nodegit.Repository | | - Returns: Promise<[SyncResult](./git-documentdb.syncresult.md) > @@ -32,11 +25,31 @@ Call init() once just after creating an instance. ## Exceptions -[Err.RemoteRepositoryConnectError](./git-documentdb.err.remoterepositoryconnecterror.md) +[Err.CannotCreateRemoteRepositoryError](./git-documentdb.err.cannotcreateremoterepositoryerror.md) + +\# Errors from RemoteEngine\[engineName\].checkFetch + +- [RemoteErr.InvalidGitRemoteError](./git-documentdb.remoteerr.invalidgitremoteerror.md) + +- [RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + +- [RemoteErr.NetworkError](./git-documentdb.remoteerr.networkerror.md) + +- [RemoteErr.HTTPError401AuthorizationRequired](./git-documentdb.remoteerr.httperror401authorizationrequired.md) + +- [RemoteErr.HTTPError404NotFound](./git-documentdb.remoteerr.httperror404notfound.md) + +- [RemoteErr.CannotConnectError](./git-documentdb.remoteerr.cannotconnecterror.md) + +- [RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + +- [RemoteErr.InvalidRepositoryURLError](./git-documentdb.remoteerr.invalidrepositoryurlerror.md) + +- [RemoteErr.InvalidSSHKeyPathError](./git-documentdb.remoteerr.invalidsshkeypatherror.md) -[Err.PushWorkerError](./git-documentdb.err.pushworkererror.md) +- [RemoteErr.InvalidAuthenticationTypeError](./git-documentdb.remoteerr.invalidauthenticationtypeerror.md) -[Err.NoMergeBaseFoundError](./git-documentdb.err.nomergebasefounderror.md) +Errors from [Sync.trySync()](./git-documentdb.sync.trysync.md) -[Err.SyncWorkerError](./git-documentdb.err.syncworkererror.md) +Errors from [Sync.tryPush()](./git-documentdb.sync.trypush.md) diff --git a/docs-api/git-documentdb.sync.md b/docs-api/git-documentdb.sync.md index e481353c..370ff77b 100644 --- a/docs-api/git-documentdb.sync.md +++ b/docs-api/git-documentdb.sync.md @@ -29,13 +29,14 @@ export declare class Sync implements SyncInterface | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [credentialCallbacks](./git-documentdb.sync.credentialcallbacks.md) | | { \[key: string\]: any; } | Callback for authentication | +| [engine](./git-documentdb.sync.engine.md) | | string | | | [jsonDiff](./git-documentdb.sync.jsondiff.md) | | JsonDiff | JsonDiff | | [jsonPatch](./git-documentdb.sync.jsonpatch.md) | | JsonPatchOT | JsonPatch | | [options](./git-documentdb.sync.options.md) | | Required<[RemoteOptions](./git-documentdb.remoteoptions.md) > | Get a clone of remote options | +| [remoteName](./git-documentdb.sync.remotename.md) | | string | remoteName | | [remoteRepository](./git-documentdb.sync.remoterepository.md) | | [RemoteRepository](./git-documentdb.remoterepository.md) | Remote repository | | [remoteURL](./git-documentdb.sync.remoteurl.md) | | string | remoteURL | -| [upstreamBranch](./git-documentdb.sync.upstreambranch.md) | | string | upstreamBranch | +| [runBeforeLiveSync](./git-documentdb.sync.runbeforelivesync.md) | | (() => void) \| undefined | runBeforeLiveSync This function is executed just before each automated(live) synchronization event is queued. Set undefined to stop it. | ## Methods @@ -43,13 +44,12 @@ export declare class Sync implements SyncInterface | --- | --- | --- | | [close()](./git-documentdb.sync.close.md) | | Stop and clear remote connection | | [currentRetries()](./git-documentdb.sync.currentretries.md) | | Return current retry count (incremental) | -| [enqueuePushTask()](./git-documentdb.sync.enqueuepushtask.md) | | Enqueue push task to TaskQueue | -| [enqueueSyncTask()](./git-documentdb.sync.enqueuesynctask.md) | | Enqueue sync task to TaskQueue | -| [init(repos)](./git-documentdb.sync.init.md) | | Create remote connection | +| [enqueueSyncTask(calledAsPeriodicTask)](./git-documentdb.sync.enqueuesynctask.md) | | Enqueue sync task to TaskQueue | +| [init()](./git-documentdb.sync.init.md) | | Initialize remote connection | | [off(event, callback)](./git-documentdb.sync.off.md) | | Remove SyncEvent handler | | [on(event, callback, collectionPath)](./git-documentdb.sync.on.md) | | Add SyncEvent handler | | [pause()](./git-documentdb.sync.pause.md) | | Pause synchronization | | [resume(options)](./git-documentdb.sync.resume.md) | | Resume synchronization | -| [tryPush()](./git-documentdb.sync.trypush.md) | | Try to push with retries | +| [tryPush()](./git-documentdb.sync.trypush.md) | | Try to push | | [trySync()](./git-documentdb.sync.trysync.md) | | Try to sync with retries | diff --git a/docs-api/git-documentdb.sync.remotename.md b/docs-api/git-documentdb.sync.remotename.md new file mode 100644 index 00000000..925fa157 --- /dev/null +++ b/docs-api/git-documentdb.sync.remotename.md @@ -0,0 +1,17 @@ +--- +sidebar_label: remoteName +title: Sync.remoteName property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Sync](./git-documentdb.sync.md) > [remoteName](./git-documentdb.sync.remotename.md) + +## Sync.remoteName property + +remoteName + +Signature: + +```typescript +get remoteName(): string; +``` diff --git a/docs-api/git-documentdb.sync.runbeforelivesync.md b/docs-api/git-documentdb.sync.runbeforelivesync.md new file mode 100644 index 00000000..e4bc076a --- /dev/null +++ b/docs-api/git-documentdb.sync.runbeforelivesync.md @@ -0,0 +1,19 @@ +--- +sidebar_label: runBeforeLiveSync +title: Sync.runBeforeLiveSync property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Sync](./git-documentdb.sync.md) > [runBeforeLiveSync](./git-documentdb.sync.runbeforelivesync.md) + +## Sync.runBeforeLiveSync property + +runBeforeLiveSync + +This function is executed just before each automated(live) synchronization event is queued. Set undefined to stop it. + +Signature: + +```typescript +runBeforeLiveSync: (() => void) | undefined; +``` diff --git a/docs-api/git-documentdb.sync.trypush.md b/docs-api/git-documentdb.sync.trypush.md index 6f6f3fd4..e36fae58 100644 --- a/docs-api/git-documentdb.sync.trypush.md +++ b/docs-api/git-documentdb.sync.trypush.md @@ -8,22 +8,52 @@ hide_title: true ## Sync.tryPush() method -Try to push with retries +Try to push Signature: ```typescript -tryPush(): Promise; +tryPush(): Promise; ``` Returns: -Promise<[SyncResultPush](./git-documentdb.syncresultpush.md) \| [SyncResultCancel](./git-documentdb.syncresultcancel.md) > +Promise<[SyncResultPush](./git-documentdb.syncresultpush.md) \| [SyncResultCancel](./git-documentdb.syncresultcancel.md) \| [SyncResultNop](./git-documentdb.syncresultnop.md) > ## Exceptions -[Err.PushNotAllowedError](./git-documentdb.err.pushnotallowederror.md) (from this and enqueuePushTask) +[Err.PushNotAllowedError](./git-documentdb.err.pushnotallowederror.md) -[Err.PushWorkerError](./git-documentdb.err.pushworkererror.md) (from this and enqueuePushTask) +\# Errors from push -[Err.UnfetchedCommitExistsError](./git-documentdb.err.unfetchedcommitexistserror.md) (from this and enqueuePushTask) +- [RemoteErr.InvalidGitRemoteError](./git-documentdb.remoteerr.invalidgitremoteerror.md) + +- [RemoteErr.UnfetchedCommitExistsError](./git-documentdb.remoteerr.unfetchedcommitexistserror.md) + +- [RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + +- [RemoteErr.NetworkError](./git-documentdb.remoteerr.networkerror.md) + +- [RemoteErr.HTTPError401AuthorizationRequired](./git-documentdb.remoteerr.httperror401authorizationrequired.md) + +- [RemoteErr.HTTPError404NotFound](./git-documentdb.remoteerr.httperror404notfound.md) + +- [RemoteErr.HTTPError403Forbidden](./git-documentdb.remoteerr.httperror403forbidden.md) + +- [RemoteErr.CannotConnectError](./git-documentdb.remoteerr.cannotconnecterror.md) + +- [RemoteErr.UnfetchedCommitExistsError](./git-documentdb.remoteerr.unfetchedcommitexistserror.md) + +- [RemoteErr.CannotConnectError](./git-documentdb.remoteerr.cannotconnecterror.md) + +- [RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + +- [RemoteErr.InvalidRepositoryURLError](./git-documentdb.remoteerr.invalidrepositoryurlerror.md) + +- [RemoteErr.InvalidSSHKeyPathError](./git-documentdb.remoteerr.invalidsshkeypatherror.md) + +- [RemoteErr.InvalidAuthenticationTypeError](./git-documentdb.remoteerr.invalidauthenticationtypeerror.md) + +\# Errors from getChanges + +- [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.sync.trysync.md b/docs-api/git-documentdb.sync.trysync.md index 7c1be9ad..1388fa75 100644 --- a/docs-api/git-documentdb.sync.trysync.md +++ b/docs-api/git-documentdb.sync.trysync.md @@ -21,11 +21,61 @@ Promise<[SyncResult](./git-documentdb.syncresult.md) > ## Exceptions -[Err.PushNotAllowedError](./git-documentdb.err.pushnotallowederror.md) (from this and enqueueSyncTask) +[Err.PushNotAllowedError](./git-documentdb.err.pushnotallowederror.md) -[Err.SyncWorkerError](./git-documentdb.err.syncworkererror.md) (from enqueueSyncTask) +[Err.CombineDatabaseError](./git-documentdb.err.combinedatabaseerror.md) -[Err.NoMergeBaseFoundError](./git-documentdb.err.nomergebasefounderror.md) (from enqueueSyncTask) +\# Errors from syncWorker -[Err.UnfetchedCommitExistsError](./git-documentdb.err.unfetchedcommitexistserror.md) (from enqueueSyncTask) +- [Err.NoMergeBaseFoundError](./git-documentdb.err.nomergebasefounderror.md) + +- [Err.ThreeWayMergeError](./git-documentdb.err.threewaymergeerror.md) + +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) + +\# Errors from fetch, pushWorker + +- [RemoteErr.InvalidGitRemoteError](./git-documentdb.remoteerr.invalidgitremoteerror.md) + +- [RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + +- [RemoteErr.NetworkError](./git-documentdb.remoteerr.networkerror.md) + +- [RemoteErr.HTTPError401AuthorizationRequired](./git-documentdb.remoteerr.httperror401authorizationrequired.md) + +- [RemoteErr.HTTPError404NotFound](./git-documentdb.remoteerr.httperror404notfound.md) + +- [RemoteErr.CannotConnectError](./git-documentdb.remoteerr.cannotconnecterror.md) + +- [RemoteErr.InvalidURLFormatError](./git-documentdb.remoteerr.invalidurlformaterror.md) + +- [RemoteErr.InvalidRepositoryURLError](./git-documentdb.remoteerr.invalidrepositoryurlerror.md) + +- [RemoteErr.InvalidSSHKeyPathError](./git-documentdb.remoteerr.invalidsshkeypatherror.md) + +- [RemoteErr.InvalidAuthenticationTypeError](./git-documentdb.remoteerr.invalidauthenticationtypeerror.md) + +\# Errors from pushWorker + +- [RemoteErr.HTTPError403Forbidden](./git-documentdb.remoteerr.httperror403forbidden.md) + +- [RemoteErr.UnfetchedCommitExistsError](./git-documentdb.remoteerr.unfetchedcommitexistserror.md) + +\# Errors from merge + +- [Err.InvalidConflictStateError](./git-documentdb.err.invalidconflictstateerror.md) + +- [Err.CannotDeleteDataError](./git-documentdb.err.cannotdeletedataerror.md) + +- [Err.InvalidDocTypeError](./git-documentdb.err.invaliddoctypeerror.md) + +- [Err.InvalidConflictResolutionStrategyError](./git-documentdb.err.invalidconflictresolutionstrategyerror.md) + +- [Err.CannotCreateDirectoryError](./git-documentdb.err.cannotcreatedirectoryerror.md) + +- [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) + +\# Errors from getChanges + +- [Err.InvalidJsonObjectError](./git-documentdb.err.invalidjsonobjecterror.md) diff --git a/docs-api/git-documentdb.sync.upstreambranch.md b/docs-api/git-documentdb.sync.upstreambranch.md deleted file mode 100644 index 1649fe36..00000000 --- a/docs-api/git-documentdb.sync.upstreambranch.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar_label: upstreamBranch -title: Sync.upstreamBranch property -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [Sync](./git-documentdb.sync.md) > [upstreamBranch](./git-documentdb.sync.upstreambranch.md) - -## Sync.upstreamBranch property - -upstreamBranch - -Signature: - -```typescript -get upstreamBranch(): string; -``` diff --git a/docs-api/git-documentdb.syncinterface.credentialcallbacks.md b/docs-api/git-documentdb.syncinterface.credentialcallbacks.md deleted file mode 100644 index 97c8df78..00000000 --- a/docs-api/git-documentdb.syncinterface.credentialcallbacks.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar_label: credentialCallbacks -title: SyncInterface.credentialCallbacks property -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SyncInterface](./git-documentdb.syncinterface.md) > [credentialCallbacks](./git-documentdb.syncinterface.credentialcallbacks.md) - -## SyncInterface.credentialCallbacks property - -Signature: - -```typescript -credentialCallbacks: { - [key: string]: any; - }; -``` diff --git a/docs-api/git-documentdb.syncinterface.engine.md b/docs-api/git-documentdb.syncinterface.engine.md new file mode 100644 index 00000000..45571012 --- /dev/null +++ b/docs-api/git-documentdb.syncinterface.engine.md @@ -0,0 +1,15 @@ +--- +sidebar_label: engine +title: SyncInterface.engine property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SyncInterface](./git-documentdb.syncinterface.md) > [engine](./git-documentdb.syncinterface.engine.md) + +## SyncInterface.engine property + +Signature: + +```typescript +engine: string; +``` diff --git a/docs-api/git-documentdb.syncinterface.enqueuepushtask.md b/docs-api/git-documentdb.syncinterface.enqueuepushtask.md deleted file mode 100644 index d1ea72a8..00000000 --- a/docs-api/git-documentdb.syncinterface.enqueuepushtask.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_label: enqueuePushTask() -title: SyncInterface.enqueuePushTask() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SyncInterface](./git-documentdb.syncinterface.md) > [enqueuePushTask](./git-documentdb.syncinterface.enqueuepushtask.md) - -## SyncInterface.enqueuePushTask() method - -Signature: - -```typescript -enqueuePushTask(): Promise; -``` -Returns: - -Promise<[SyncResultPush](./git-documentdb.syncresultpush.md) \| [SyncResultCancel](./git-documentdb.syncresultcancel.md) > - diff --git a/docs-api/git-documentdb.syncinterface.enqueuesynctask.md b/docs-api/git-documentdb.syncinterface.enqueuesynctask.md deleted file mode 100644 index 061279fb..00000000 --- a/docs-api/git-documentdb.syncinterface.enqueuesynctask.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_label: enqueueSyncTask() -title: SyncInterface.enqueueSyncTask() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SyncInterface](./git-documentdb.syncinterface.md) > [enqueueSyncTask](./git-documentdb.syncinterface.enqueuesynctask.md) - -## SyncInterface.enqueueSyncTask() method - -Signature: - -```typescript -enqueueSyncTask(): Promise; -``` -Returns: - -Promise<[SyncResult](./git-documentdb.syncresult.md) > - diff --git a/docs-api/git-documentdb.syncinterface.init.md b/docs-api/git-documentdb.syncinterface.init.md index 50c0c1b6..89eb179e 100644 --- a/docs-api/git-documentdb.syncinterface.init.md +++ b/docs-api/git-documentdb.syncinterface.init.md @@ -13,15 +13,8 @@ hide_title: true Signature: ```typescript -init(repos: nodegit.Repository): Promise; +init(): Promise; ``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| repos | nodegit.Repository | | - Returns: Promise<[SyncResult](./git-documentdb.syncresult.md) > diff --git a/docs-api/git-documentdb.syncinterface.md b/docs-api/git-documentdb.syncinterface.md index 247c55bb..41c6d8f1 100644 --- a/docs-api/git-documentdb.syncinterface.md +++ b/docs-api/git-documentdb.syncinterface.md @@ -20,13 +20,14 @@ export interface SyncInterface | Property | Type | Description | | --- | --- | --- | -| [credentialCallbacks](./git-documentdb.syncinterface.credentialcallbacks.md) | { \[key: string\]: any; } | | +| [engine](./git-documentdb.syncinterface.engine.md) | string | | | [jsonDiff](./git-documentdb.syncinterface.jsondiff.md) | JsonDiff | | | [jsonPatch](./git-documentdb.syncinterface.jsonpatch.md) | IJsonPatch | | | [options](./git-documentdb.syncinterface.options.md) | [RemoteOptions](./git-documentdb.remoteoptions.md) | | +| [remoteName](./git-documentdb.syncinterface.remotename.md) | string | | | [remoteRepository](./git-documentdb.syncinterface.remoterepository.md) | [RemoteRepository](./git-documentdb.remoterepository.md) | | | [remoteURL](./git-documentdb.syncinterface.remoteurl.md) | string | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties (readonly) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | -| [upstreamBranch](./git-documentdb.syncinterface.upstreambranch.md) | string | | +| [runBeforeLiveSync](./git-documentdb.syncinterface.runbeforelivesync.md) | (() => void) \| undefined | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | ## Methods @@ -34,9 +35,7 @@ export interface SyncInterface | --- | --- | | [close()](./git-documentdb.syncinterface.close.md) | | | [currentRetries()](./git-documentdb.syncinterface.currentretries.md) | | -| [enqueuePushTask()](./git-documentdb.syncinterface.enqueuepushtask.md) | | -| [enqueueSyncTask()](./git-documentdb.syncinterface.enqueuesynctask.md) | | -| [init(repos)](./git-documentdb.syncinterface.init.md) | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public methods \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | +| [init()](./git-documentdb.syncinterface.init.md) | \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public methods \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* | | [off(event, callback)](./git-documentdb.syncinterface.off.md) | | | [on(event, callback, collectionPath)](./git-documentdb.syncinterface.on.md) | | | [pause()](./git-documentdb.syncinterface.pause.md) | | diff --git a/docs-api/git-documentdb.syncinterface.off.md b/docs-api/git-documentdb.syncinterface.off.md index ab9388a2..41f8487f 100644 --- a/docs-api/git-documentdb.syncinterface.off.md +++ b/docs-api/git-documentdb.syncinterface.off.md @@ -11,7 +11,7 @@ hide_title: true Signature: ```typescript -off(event: SyncEvent, callback: SyncCallback): void; +off(event: SyncEvent, callback: SyncCallback): SyncInterface; ``` ## Parameters @@ -23,5 +23,5 @@ off(event: SyncEvent, callback: SyncCallback): void; Returns: -void +[SyncInterface](./git-documentdb.syncinterface.md) diff --git a/docs-api/git-documentdb.syncinterface.remotename.md b/docs-api/git-documentdb.syncinterface.remotename.md new file mode 100644 index 00000000..be112f60 --- /dev/null +++ b/docs-api/git-documentdb.syncinterface.remotename.md @@ -0,0 +1,15 @@ +--- +sidebar_label: remoteName +title: SyncInterface.remoteName property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SyncInterface](./git-documentdb.syncinterface.md) > [remoteName](./git-documentdb.syncinterface.remotename.md) + +## SyncInterface.remoteName property + +Signature: + +```typescript +remoteName: string; +``` diff --git a/docs-api/git-documentdb.syncinterface.runbeforelivesync.md b/docs-api/git-documentdb.syncinterface.runbeforelivesync.md new file mode 100644 index 00000000..f4cdc111 --- /dev/null +++ b/docs-api/git-documentdb.syncinterface.runbeforelivesync.md @@ -0,0 +1,17 @@ +--- +sidebar_label: runBeforeLiveSync +title: SyncInterface.runBeforeLiveSync property +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SyncInterface](./git-documentdb.syncinterface.md) > [runBeforeLiveSync](./git-documentdb.syncinterface.runbeforelivesync.md) + +## SyncInterface.runBeforeLiveSync property + +\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* Public properties \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* + +Signature: + +```typescript +runBeforeLiveSync: (() => void) | undefined; +``` diff --git a/docs-api/git-documentdb.syncinterface.trypush.md b/docs-api/git-documentdb.syncinterface.trypush.md index 5cb47db0..bd7867d5 100644 --- a/docs-api/git-documentdb.syncinterface.trypush.md +++ b/docs-api/git-documentdb.syncinterface.trypush.md @@ -11,9 +11,9 @@ hide_title: true Signature: ```typescript -tryPush(): Promise; +tryPush(): Promise; ``` Returns: -Promise<[SyncResultPush](./git-documentdb.syncresultpush.md) \| [SyncResultCancel](./git-documentdb.syncresultcancel.md) > +Promise<[SyncResultPush](./git-documentdb.syncresultpush.md) \| [SyncResultCancel](./git-documentdb.syncresultcancel.md) \| [SyncResultNop](./git-documentdb.syncresultnop.md) > diff --git a/docs-api/git-documentdb.syncinterface.upstreambranch.md b/docs-api/git-documentdb.syncinterface.upstreambranch.md deleted file mode 100644 index cab3081e..00000000 --- a/docs-api/git-documentdb.syncinterface.upstreambranch.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_label: upstreamBranch -title: SyncInterface.upstreamBranch property -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [SyncInterface](./git-documentdb.syncinterface.md) > [upstreamBranch](./git-documentdb.syncinterface.upstreambranch.md) - -## SyncInterface.upstreamBranch property - -Signature: - -```typescript -upstreamBranch: string; -``` diff --git a/docs-api/git-documentdb.taskmetadata.md b/docs-api/git-documentdb.taskmetadata.md index d6701e51..fc36f197 100644 --- a/docs-api/git-documentdb.taskmetadata.md +++ b/docs-api/git-documentdb.taskmetadata.md @@ -20,6 +20,8 @@ export declare type TaskMetadata = { shortName?: string; collectionPath?: string; enqueueTime?: string; + syncRemoteName?: string; + debounceTime?: number; }; ``` References: diff --git a/docs-api/git-documentdb.taskqueue._constructor_.md b/docs-api/git-documentdb.taskqueue._constructor_.md index 7a9d12c3..c76e19b3 100644 --- a/docs-api/git-documentdb.taskqueue._constructor_.md +++ b/docs-api/git-documentdb.taskqueue._constructor_.md @@ -13,12 +13,16 @@ Constructor Signature: ```typescript -constructor(logger: Logger); +constructor(logger: ColoredLogger); ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| logger | Logger | | +| logger | ColoredLogger | | + +## Remarks + +Must call start() after new TaskQueue() diff --git a/docs-api/git-documentdb.taskqueue.clear.md b/docs-api/git-documentdb.taskqueue.clear.md deleted file mode 100644 index f8874d62..00000000 --- a/docs-api/git-documentdb.taskqueue.clear.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -sidebar_label: clear() -title: TaskQueue.clear() method -hide_title: true ---- - -[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [TaskQueue](./git-documentdb.taskqueue.md) > [clear](./git-documentdb.taskqueue.clear.md) - -## TaskQueue.clear() method - -Clear TaskQueue - -Signature: - -```typescript -clear(): void; -``` -Returns: - -void - diff --git a/docs-api/git-documentdb.taskqueue.md b/docs-api/git-documentdb.taskqueue.md index 288e988e..30cc8597 100644 --- a/docs-api/git-documentdb.taskqueue.md +++ b/docs-api/git-documentdb.taskqueue.md @@ -26,9 +26,10 @@ export declare class TaskQueue | Method | Modifiers | Description | | --- | --- | --- | -| [clear()](./git-documentdb.taskqueue.clear.md) | | Clear TaskQueue | | [currentStatistics()](./git-documentdb.taskqueue.currentstatistics.md) | | Get current statistics | | [currentTaskId()](./git-documentdb.taskqueue.currenttaskid.md) | | Get current task ID | | [getEnqueueTime()](./git-documentdb.taskqueue.getenqueuetime.md) | | Get enqueue time | | [length()](./git-documentdb.taskqueue.length.md) | | Get length of TaskQueue | +| [start()](./git-documentdb.taskqueue.start.md) | | Start TaskQueue | +| [stop()](./git-documentdb.taskqueue.stop.md) | | Stop TaskQueue | diff --git a/docs-api/git-documentdb.taskqueue.start.md b/docs-api/git-documentdb.taskqueue.start.md new file mode 100644 index 00000000..7b37bc97 --- /dev/null +++ b/docs-api/git-documentdb.taskqueue.start.md @@ -0,0 +1,21 @@ +--- +sidebar_label: start() +title: TaskQueue.start() method +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [TaskQueue](./git-documentdb.taskqueue.md) > [start](./git-documentdb.taskqueue.start.md) + +## TaskQueue.start() method + +Start TaskQueue + +Signature: + +```typescript +start(): void; +``` +Returns: + +void + diff --git a/docs-api/git-documentdb.taskqueue.stop.md b/docs-api/git-documentdb.taskqueue.stop.md new file mode 100644 index 00000000..c120cfae --- /dev/null +++ b/docs-api/git-documentdb.taskqueue.stop.md @@ -0,0 +1,21 @@ +--- +sidebar_label: stop() +title: TaskQueue.stop() method +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [TaskQueue](./git-documentdb.taskqueue.md) > [stop](./git-documentdb.taskqueue.stop.md) + +## TaskQueue.stop() method + +Stop TaskQueue + +Signature: + +```typescript +stop(): void; +``` +Returns: + +void + diff --git a/docs-api/git-documentdb.yaml_postfix.md b/docs-api/git-documentdb.yaml_postfix.md new file mode 100644 index 00000000..0c428288 --- /dev/null +++ b/docs-api/git-documentdb.yaml_postfix.md @@ -0,0 +1,16 @@ +--- +sidebar_label: YAML_POSTFIX variable +title: YAML_POSTFIX variable +hide_title: true +--- + +[Home](./index.md) > [git-documentdb](./git-documentdb.md) > [YAML\_POSTFIX](./git-documentdb.yaml_postfix.md) + +## YAML\_POSTFIX variable + + +Signature: + +```typescript +YAML_POSTFIX = ".yml" +``` diff --git a/etc/git-documentdb.api.md b/etc/git-documentdb.api.md index eada2f36..d810e59c 100644 --- a/etc/git-documentdb.api.md +++ b/etc/git-documentdb.api.md @@ -4,9 +4,9 @@ ```ts +import { ILogObject } from 'tslog'; import { JSONOp } from 'ot-json1'; import { Logger } from 'tslog'; -import nodegit from '@sosuisen/nodegit'; import { TLogLevelName } from 'tslog'; // @public @@ -45,11 +45,6 @@ export type ChangedFileUpdate = { new: FatDoc; }; -// Warning: (ae-internal-missing-underscore) The name "cloneRepository" should be prefixed with an underscore because the declaration is marked as @internal -// -// @internal -export function cloneRepository(workingDir: string, remoteOptions: RemoteOptions, logger?: Logger): Promise; - // @public export class Collection implements ICollection { constructor(gitDDB: GitDDBInterface, collectionPathFromParent?: CollectionPath, parent?: ICollection, options?: CollectionOptions); @@ -62,7 +57,7 @@ export class Collection implements ICollection { deleteFatDoc(shortName: string, options?: DeleteOptions): Promise; find(options?: FindOptions): Promise; findFatDoc(options?: FindOptions): Promise; - generateId(): string; + generateId(seedTime?: number): string; get(_id: string): Promise; getCollections(dirPath?: string): Promise; getDocByOid(fileOid: string, docType?: DocType): Promise; @@ -113,11 +108,31 @@ export interface CollectionInterface { // @public export type CollectionOptions = { namePrefix?: string; + debounceTime?: number; + idGenerator?: () => string; }; // @public export type CollectionPath = string; +// Warning: (ae-internal-missing-underscore) The name "ColoredLog" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export type ColoredLog = (mes: string, colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string) => void; + +// Warning: (ae-internal-missing-underscore) The name "ColoredLogger" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export type ColoredLogger = { + silly: ColoredLog; + debug: ColoredLog; + trace: ColoredLog; + info: ColoredLog; + warn: ColoredLog; + error: ColoredLog; + fatal: ColoredLog; +}; + // @public export type CombineDbStrategies = 'throw-error' | 'combine-head-with-ours' | 'combine-head-with-theirs' | 'combine-history-with-ours' | 'combine-history-with-theirs' | 'replace-with-ours' | 'replace-with-theirs'; @@ -133,6 +148,7 @@ export type ConnectionSettings = ConnectionSettingsNone | ConnectionSettingsGitH // @public export type ConnectionSettingsGitHub = { type: 'github'; + engine?: string; personalAccessToken?: string; private?: boolean; }; @@ -140,11 +156,13 @@ export type ConnectionSettingsGitHub = { // @public export type ConnectionSettingsNone = { type: 'none'; + engine?: string; }; // @public export type ConnectionSettingsSSH = { type: 'ssh'; + engine?: string; privateKeyPath: string; publicKeyPath: string; passPhrase?: string; @@ -221,6 +239,7 @@ export type DatabaseInfo = { dbId: string; creator: string; version: string; + serialize: SerializeFormatLabel; }; // @public @@ -236,6 +255,9 @@ export type DatabaseOptions = { dbName: string; logLevel?: TLogLevelName; schema?: Schema; + serialize?: SerializeFormatLabel; + logToTransport?: (logObject: ILogObject) => void; + logColorEnabled?: boolean; }; // @public (undocumented) @@ -306,6 +328,9 @@ export type DuplicatedFile = { duplicate: DocMetadata; }; +// @public +export function encodeToGitRemoteName(remoteURL: string): string; + // @public export namespace Err { // (undocumented) @@ -316,7 +341,7 @@ export namespace Err { constructor(e: string); } // (undocumented) - export class CannotConnectError extends BaseError { + export class CannotConnectRemoteRepositoryError extends BaseError { constructor(retry: number, url: string, mes: string); // (undocumented) retry: number; @@ -366,14 +391,6 @@ export namespace Err { constructor(e?: unknown); } // (undocumented) - export class FetchConnectionFailedError extends BaseError { - constructor(mes: unknown); - } - // (undocumented) - export class FetchPermissionDeniedError extends BaseError { - constructor(mes: unknown); - } - // (undocumented) export class FileRemoveTimeoutError extends BaseError { constructor(); } @@ -382,14 +399,6 @@ export namespace Err { constructor(mes: string); } // (undocumented) - export class GitPushError extends BaseError { - constructor(mes: string); - } - // (undocumented) - export class HTTPNetworkError extends BaseError { - constructor(mes: unknown); - } - // (undocumented) export class HttpProtocolRequiredError extends BaseError { constructor(url: unknown); } @@ -398,10 +407,6 @@ export namespace Err { constructor(min: unknown, current: unknown); } // (undocumented) - export class InvalidAuthenticationTypeError extends BaseError { - constructor(type: string); - } - // (undocumented) export class InvalidCollectionPathCharacterError extends BaseError { constructor(name: unknown); } @@ -410,6 +415,10 @@ export namespace Err { constructor(collectionPath: unknown, minLength: unknown, maxLength: unknown); } // (undocumented) + export class InvalidConflictResolutionStrategyError extends BaseError { + constructor(); + } + // (undocumented) export class InvalidConflictStateError extends BaseError { constructor(mes: unknown); } @@ -442,18 +451,6 @@ export namespace Err { constructor(name: unknown); } // (undocumented) - export class InvalidRepositoryURLError extends BaseError { - constructor(url: unknown); - } - // (undocumented) - export class InvalidSSHKeyPathError extends BaseError { - constructor(); - } - // (undocumented) - export class InvalidURLError extends BaseError { - constructor(url: unknown); - } - // (undocumented) export class InvalidWorkingDirectoryPathLengthError extends BaseError { constructor(path: unknown, minLength: unknown, maxLength: unknown); } @@ -466,18 +463,10 @@ export namespace Err { constructor(); } // (undocumented) - export class PushConnectionFailedError extends BaseError { - constructor(mes: unknown); - } - // (undocumented) export class PushNotAllowedError extends BaseError { constructor(direction: unknown); } // (undocumented) - export class PushPermissionDeniedError extends BaseError { - constructor(mes: unknown); - } - // (undocumented) export class PushWorkerError extends BaseError { constructor(mes: unknown); } @@ -486,14 +475,6 @@ export namespace Err { constructor(url: unknown); } // (undocumented) - export class RemoteRepositoryConnectError extends BaseError { - constructor(mes: unknown); - } - // (undocumented) - export class RemoteRepositoryNotFoundError extends BaseError { - constructor(url: unknown); - } - // (undocumented) export class RepositoryNotFoundError extends BaseError { constructor(path: unknown); } @@ -522,10 +503,6 @@ export namespace Err { constructor(mes: unknown); } // (undocumented) - export class SyncWorkerFetchError extends BaseError { - constructor(mes: string); - } - // (undocumented) export class TaskCancelError extends BaseError { constructor(taskId: unknown); } @@ -557,11 +534,7 @@ export namespace Err { export class UndefinedSyncError extends BaseError { constructor(e?: unknown); } - // (undocumented) - export class UnfetchedCommitExistsError extends BaseError { - constructor(); - } - {}; + {}; } // @public @@ -582,6 +555,9 @@ export type FatTextDoc = TextDocMetadata & { doc: string; }; +// @public (undocumented) +export const FILE_CREATE_TIMEOUT = 2000; + // @public (undocumented) export const FILE_REMOVE_TIMEOUT = 7000; @@ -596,6 +572,9 @@ export type FindOptions = { // @public (undocumented) export const FIRST_COMMIT_MESSAGE = "first commit"; +// @public (undocumented) +export const FRONT_MATTER_POSTFIX = ".md"; + // Warning: (ae-internal-missing-underscore) The name "generateDatabaseId" should be prefixed with an underscore because the declaration is marked as @internal // // @internal @@ -615,9 +594,6 @@ export type GetOptions = { forceDocType?: DocType; }; -// @public (undocumented) -export const GIT_DOCUMENTDB_APP_INFO_ID = ".gitddb/app"; - // @public (undocumented) export const GIT_DOCUMENTDB_INFO_ID = ".gitddb/info"; @@ -642,6 +618,7 @@ export interface GitDDBInterface { dbId: string; // (undocumented) dbName: string; + // (undocumented) defaultBranch: string; // (undocumented) destroy(options: DatabaseCloseOption): Promise<{ @@ -658,35 +635,28 @@ export interface GitDDBInterface { // (undocumented) isOpened: boolean; // (undocumented) - loadAppInfo(): { - [key: string]: any; - }; - // (undocumented) loadAuthor(): Promise; // (undocumented) loadDbInfo(): void; // (undocumented) localDir: string; + // Warning: (ae-incompatible-release-tags) The symbol "logger" is marked as @public, but its signature references "ColoredLogger" which is marked as @internal + // // (undocumented) - logger: Logger; + logger: ColoredLogger; logLevel: TLogLevelName; open(options?: OpenOptions): Promise; // (undocumented) removeSync(remoteURL: string): void; // (undocumented) - repository(): nodegit.Repository | undefined; - // (undocumented) rootCollection: ICollection; // (undocumented) - saveAppInfo(info: { - [key: string]: any; - }): void; - // (undocumented) saveAuthor(): Promise; // (undocumented) schema: Schema; - // (undocumented) - setRepository(repos: nodegit.Repository): void; + // Warning: (ae-forgotten-export) The symbol "SerializeFormatJSON" needs to be exported by the entry point main.d.ts + // Warning: (ae-forgotten-export) The symbol "SerializeFormatFrontMatter" needs to be exported by the entry point main.d.ts + serializeFormat: SerializeFormatJSON | SerializeFormatFrontMatter; // (undocumented) sync(options: RemoteOptions, getSyncResult: boolean): Promise<[SyncInterface, SyncResult]>; // (undocumented) @@ -694,6 +664,8 @@ export interface GitDDBInterface { // (undocumented) taskQueue: TaskQueue; // (undocumented) + tsLogger: Logger; + // (undocumented) validator: Validator; // (undocumented) workingDir: string; @@ -739,14 +711,15 @@ export class GitDocumentDB implements GitDDBInterface, CRUDInterface, Collection insertFatDoc(name: string | undefined | null, doc: JsonDoc | string | Uint8Array, options?: PutOptions): Promise; get isClosing(): boolean; get isOpened(): boolean; - loadAppInfo(): Promise; loadAuthor(): Promise; // @internal loadDbInfo(): Promise; get localDir(): string; - get logger(): Logger; + // Warning: (ae-incompatible-release-tags) The symbol "logger" is marked as @public, but its signature references "ColoredLogger" which is marked as @internal + get logger(): ColoredLogger; get logLevel(): TLogLevelName; set logLevel(level: TLogLevelName); + get logToTransport(): ((logObject: ILogObject) => void) | undefined; // @eventProperty offSyncEvent(remoteURL: string, event: SyncEvent, callback: SyncCallback): void; // @eventProperty @@ -756,29 +729,27 @@ export class GitDocumentDB implements GitDDBInterface, CRUDInterface, Collection // @eventProperty onSyncEvent(sync: SyncInterface, event: SyncEvent, callback: SyncCallback): SyncInterface; open(openOptions?: OpenOptions): Promise; + // (undocumented) + static plugin(obj: any): void; put(jsonDoc: JsonDoc, options?: PutOptions): Promise; put(_id: string | undefined | null, jsonDoc: JsonDoc, options?: PutOptions): Promise; putFatDoc(name: string | undefined | null, doc: JsonDoc | Uint8Array | string, options?: PutOptions): Promise; removeSync(remoteURL: string): void; - // @deprecated - repository(): nodegit.Repository | undefined; get rootCollection(): ICollection; - saveAppInfo(info: { - [key: string]: any; - }): Promise; saveAuthor(): Promise; get schema(): Schema; - // @deprecated - setRepository(repos: nodegit.Repository): void; + // (undocumented) + get serializeFormat(): SerializeFormatJSON | SerializeFormatFrontMatter; sync(options: RemoteOptions): Promise; sync(options: RemoteOptions, getSyncResult: boolean): Promise<[Sync, SyncResult]>; get taskQueue(): TaskQueue; + get tsLogger(): Logger; update(jsonDoc: JsonDoc, options?: PutOptions): Promise; update(_id: string | undefined | null, jsonDoc: JsonDoc, options?: PutOptions): Promise; updateFatDoc(name: string | undefined | null, doc: JsonDoc | string | Uint8Array, options?: PutOptions): Promise; get validator(): Validator; get workingDir(): string; - } +} // @public export type HistoryFilter = { @@ -802,7 +773,7 @@ export type ICollection = CollectionInterface & CRUDInterface & SyncEventInterfa options: CollectionOptions; collectionPath: string; parent: ICollection | undefined; - generateId(): string; + generateId(seedTime?: number): string; }; // Warning: (ae-internal-missing-underscore) The name "IJsonPatch" should be prefixed with an underscore because the declaration is marked as @internal @@ -818,11 +789,12 @@ export interface IJsonPatch { } // @public (undocumented) -export const JSON_EXT = ".json"; +export const JSON_POSTFIX = ".json"; // @public -export type JsonDiffOptions = { - idOfSubtree?: string[]; +export type JsonDiffPatchOptions = { + keyInArrayedObject?: string[]; + keyOfUniqueArray?: string[]; plainTextProperties?: { [key: string]: any; }; @@ -879,6 +851,9 @@ export type OpenOptions = { createIfNotExists?: boolean; }; +// @public +export type PluginTypes = 'db' | 'remote'; + // @public (undocumented) export const PUT_APP_INFO_MESSAGE = "put appinfo"; @@ -888,6 +863,7 @@ export type PutOptions = { insertOrUpdate?: 'insert' | 'update'; taskId?: string; enqueueCallback?: (taskMetadata: TaskMetadata) => void; + debounceTime?: number; }; // @public @@ -918,6 +894,79 @@ export type PutResultText = { type: 'text'; }; +// @public +export const RemoteEngine: { + [key: string]: RemoteEngineInterface; +}; + +// Warning: (ae-internal-missing-underscore) The name "RemoteEngineInterface" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface RemoteEngineInterface { + // (undocumented) + checkFetch: (workingDir: string, options: RemoteOptions, remoteName?: string, logger?: Logger) => Promise; + // (undocumented) + clone: (workingDir: string, remoteOptions: RemoteOptions, remoteName: string, logger?: Logger) => Promise; + // (undocumented) + fetch: (workingDir: string, remoteOptions: RemoteOptions, remoteName?: string, localBranchName?: string, remoteBranchName?: string, logger?: Logger) => Promise; + // (undocumented) + name: string; + // (undocumented) + push: (workingDir: string, remoteOptions: RemoteOptions, remoteName?: string, localBranch?: string, remoteBranch?: string, logger?: Logger) => Promise; + // (undocumented) + type: string; +} + +// @public +export namespace RemoteErr { + // Warning: (ae-forgotten-export) The symbol "BaseError" needs to be exported by the entry point main.d.ts + // + // (undocumented) + export class CannotConnectError extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class HTTPError401AuthorizationRequired extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class HTTPError403Forbidden extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class HTTPError404NotFound extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class InvalidAuthenticationTypeError extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class InvalidGitRemoteError extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class InvalidRepositoryURLError extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class InvalidSSHKeyPathError extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class InvalidURLFormatError extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class NetworkError extends BaseError { + constructor(mes: unknown); + } + // (undocumented) + export class UnfetchedCommitExistsError extends BaseError { + constructor(mes: unknown); + } +} + // @public export type RemoteOptions = { remoteUrl?: string; @@ -935,19 +984,41 @@ export type RemoteOptions = { // @public export class RemoteRepository { constructor(options: RemoteOptions); - // Warning: (ae-forgotten-export) The symbol "GitRemoteAction" needs to be exported by the entry point main.d.ts - connect(repos: nodegit.Repository, credentialCallbacks: { - [key: string]: any; - }, onlyFetch?: boolean): Promise<[GitRemoteAction, 'exist' | 'create']>; create(): Promise; destroy(): Promise; - } +} // @public export type Schema = { - json: JsonDiffOptions; + json: JsonDiffPatchOptions; }; +// Warning: (ae-internal-missing-underscore) The name "SerializeFormat" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export interface SerializeFormat { + // (undocumented) + extension: (doc?: JsonDoc) => string; + // (undocumented) + firstExtension: string; + // (undocumented) + format: SerializeFormatLabel; + // (undocumented) + hasObjectExtension: (path: string) => boolean; + // (undocumented) + removeExtension: (path: string) => string; + // (undocumented) + secondExtension: string | undefined; + // (undocumented) + serialize: (doc: JsonDoc) => { + extension: string; + data: string; + }; +} + +// @public +export type SerializeFormatLabel = 'json' | 'front-matter'; + // @public (undocumented) export const SET_DATABASE_ID_MESSAGE = "set database id"; @@ -957,15 +1028,11 @@ export const SHORT_SHA_LENGTH = 7; // @public export class Sync implements SyncInterface { constructor(gitDDB: GitDDBInterface, options?: RemoteOptions); - // @internal - canNetworkConnection(): Promise; close(): void; - credentialCallbacks: { - [key: string]: any; - }; currentRetries(): number; - enqueuePushTask(): Promise; - enqueueSyncTask(): Promise; + // (undocumented) + get engine(): string; + enqueueSyncTask(calledAsPeriodicTask: boolean): Promise; // @internal eventHandlers: { change: { @@ -1005,7 +1072,7 @@ export class Sync implements SyncInterface { func: SyncErrorCallback; }[]; }; - init(repos: nodegit.Repository): Promise; + init(): Promise; // Warning: (ae-forgotten-export) The symbol "JsonDiff" needs to be exported by the entry point main.d.ts jsonDiff: JsonDiff; // Warning: (ae-forgotten-export) The symbol "JsonPatchOT" needs to be exported by the entry point main.d.ts @@ -1016,16 +1083,21 @@ export class Sync implements SyncInterface { on(event: SyncEvent, callback: SyncCallback, collectionPath?: string): this; get options(): Required; pause(): boolean; + get remoteName(): string; get remoteRepository(): RemoteRepository; get remoteURL(): string; resume(options?: { interval?: number; retry?: number; }): boolean; - tryPush(): Promise; + runBeforeLiveSync: (() => void) | undefined; + tryPush(): Promise; + // @internal + tryPushImpl(calledAsPeriodicTask: boolean): Promise; trySync(): Promise; - get upstreamBranch(): string; - } + // @internal + trySyncImpl(calledAsPeriodicTask: boolean): Promise; +} // Warning: (ae-internal-missing-underscore) The name "syncAndGetResultImpl" should be prefixed with an underscore because the declaration is marked as @internal // @@ -1079,15 +1151,9 @@ export interface SyncInterface { // (undocumented) close(): void; // (undocumented) - credentialCallbacks: { - [key: string]: any; - }; - // (undocumented) currentRetries(): number; // (undocumented) - enqueuePushTask(): Promise; - // (undocumented) - enqueueSyncTask(): Promise; + engine: string; // @internal (undocumented) eventHandlers: { change: { @@ -1127,7 +1193,7 @@ export interface SyncInterface { func: SyncErrorCallback; }[]; }; - init(repos: nodegit.Repository): Promise; + init(): Promise; // (undocumented) jsonDiff: JsonDiff; // Warning: (ae-incompatible-release-tags) The symbol "jsonPatch" is marked as @public, but its signature references "IJsonPatch" which is marked as @internal @@ -1135,7 +1201,7 @@ export interface SyncInterface { // (undocumented) jsonPatch: IJsonPatch; // (undocumented) - off(event: SyncEvent, callback: SyncCallback): void; + off(event: SyncEvent, callback: SyncCallback): SyncInterface; // (undocumented) on(event: SyncEvent, callback: SyncCallback, collectionPath?: string): SyncInterface; // (undocumented) @@ -1143,6 +1209,8 @@ export interface SyncInterface { // (undocumented) pause(): void; // (undocumented) + remoteName: string; + // (undocumented) remoteRepository: RemoteRepository; remoteURL: string; // (undocumented) @@ -1150,12 +1218,11 @@ export interface SyncInterface { interval?: number; retry?: number; }): void; + runBeforeLiveSync: (() => void) | undefined; // (undocumented) - tryPush(): Promise; + tryPush(): Promise; // (undocumented) trySync(): Promise; - // (undocumented) - upstreamBranch: string; } // @public @@ -1286,12 +1353,14 @@ export type TaskMetadata = { shortName?: string; collectionPath?: string; enqueueTime?: string; + syncRemoteName?: string; + debounceTime?: number; }; // @public export class TaskQueue { - constructor(logger: Logger); - clear(): void; + // Warning: (ae-incompatible-release-tags) The symbol "__constructor" is marked as @public, but its signature references "ColoredLogger" which is marked as @internal + constructor(logger: ColoredLogger); currentStatistics(): TaskStatistics; currentTaskId(): string | undefined; getEnqueueTime(): string; @@ -1301,7 +1370,9 @@ export class TaskQueue { // @internal pushToTaskQueue(task: Task): void; // @internal - setLogger(logger: Logger): void; + setLogger(logger: ColoredLogger): void; + start(): void; + stop(): void; // @internal (undocumented) waitCompletion(timeoutMsec: number): Promise; } @@ -1348,10 +1419,21 @@ export class Validator { validateDocument(doc: JsonDoc): void; validateId(_id: string): void; validateLocalDir(localDir: string): void; - } +} + +// Warning: (ae-internal-missing-underscore) The name "wrappingRemoteEngineError" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal +export function wrappingRemoteEngineError(remoteEngineError: BaseError): Error; // @public export type WriteOperation = 'insert' | 'update' | 'delete' | 'insert-merge' | 'update-merge'; +// @public (undocumented) +export const YAML_POSTFIX = ".yml"; + +// Warnings were encountered during analysis: +// +// src/remote/remote_engine.ts:11:30 - (ae-incompatible-release-tags) The symbol "__index" is marked as @public, but its signature references "RemoteEngineInterface" which is marked as @internal ``` diff --git a/examples/README.md b/examples/README.md index 5932c074..b779a80d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -21,4 +21,8 @@ $ npm run collection Start an example for Synchronization. ``` $ npm run sync +``` +Start an example for Plugin. +``` +$ npm run plugin ``` \ No newline at end of file diff --git a/examples/package-lock.json b/examples/package-lock.json index 5f002f38..c94b200e 100644 --- a/examples/package-lock.json +++ b/examples/package-lock.json @@ -1,23 +1,12514 @@ { "name": "git-documentdb-example", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "git-documentdb-example", + "version": "1.0.0", + "license": "MPL-2.0", + "dependencies": { + "git-documentdb": "file:..", + "git-documentdb-plugin-remote-nodegit": "^1.0.4" + }, + "devDependencies": { + "typescript": "^4.1.3" + } + }, + "..": { + "version": "0.4.7-beta.1", + "integrity": "sha512-DASPwhhEM31y0AFkVAV+j5VBA4AYUY4a4LTnzTIbBpHZW8HhoxNxy1iTsgMKrldxNmBs8+HMDv1UgjoP9ZgTtw==", + "license": "MPL-2.0", + "dependencies": { + "@octokit/rest": "^18.3.5", + "@sosuisen/jsondiffpatch": "^0.4.7", + "async-lock": "^1.3.0", + "cross-blob": "^2.0.0", + "fs-extra": "^9.1.0", + "git-documentdb-plugin-remote-nodegit": "^1.0.4", + "git-documentdb-remote-errors": "^1.0.3", + "isomorphic-git": "^1.17.1", + "js-yaml": "^4.1.0", + "ot-json1": "^1.0.2", + "rimraf": "^3.0.2", + "tslog": "^3.1.2", + "ulid": "^2.3.0", + "unicount": "^1.2.0" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.16.0", + "@octokit/types": "^6.12.2", + "@sosuisen/api-documenter": "^7.13.27", + "@types/async-lock": "^1.1.2", + "@types/fs-extra": "^9.0.12", + "@types/js-yaml": "^4.0.3", + "@types/mocha": "^8.2.2", + "@types/node": "^14.14.20", + "@types/parse-git-config": "^3.0.0", + "@types/rimraf": "^3.0.0", + "@types/sinon": "^9.0.11", + "@typescript-eslint/eslint-plugin": "^4.28.0", + "@typescript-eslint/parser": "^4.28.0", + "coveralls": "^3.1.0", + "crlf": "^1.1.1", + "cross-env": "^7.0.3", + "eslint": "^7.17.0", + "eslint-config-standardize": "^0.7.1", + "eslint-plugin-prettierx": "^0.14.0", + "eslint-plugin-unicorn": "^36.0.0", + "expect": "^27.0.2", + "hmtid": "^0.1.0", + "mocha": "^8.3.2", + "nyc": "^15.1.0", + "parse-git-config": "^3.0.0", + "sinon": "^10.0.0", + "ts-node": "^10.1.0", + "tsconfig-paths": "^3.9.0", + "typescript": "^4.3.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "../node_modules/@angular/compiler": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.5.tgz", + "integrity": "sha512-TeyhRGefTOtA9N3udMrvheafoXcz/dvTTdZLcieeZQxm1SSeaQDUQ/rUH6QTOiHVNMtjOCrZ9J5rk1A4mPYuag==", + "dev": true, + "peerDependencies": { + "tslib": "^1.10.0" + } + }, + "../node_modules/@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/compat-data": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/core": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz", + "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helpers": "^7.14.6", + "@babel/parser": "^7.14.6", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "../node_modules/@babel/core/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/@babel/core/node_modules/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 + }, + "../node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../node_modules/@babel/core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/@babel/eslint-parser": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.14.7.tgz", + "integrity": "sha512-6WPwZqO5priAGIwV6msJcdc9TsEPzYeYdS/Xuoap+/ihkgN6dzHp2bcAAwyWZ5bLzk0vvjDmKvRwkqNaiJ8BiQ==", + "dev": true, + "dependencies": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": ">=7.5.0" + } + }, + "../node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../node_modules/@babel/generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/@babel/helper-compilation-targets": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "../node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../node_modules/@babel/helper-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-get-function-arity": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-module-imports": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-module-transforms": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-optimise-call-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-replace-supers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-simple-access": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-split-export-declaration": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/helpers": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/parser": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../node_modules/@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/traverse": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/parser": "^7.14.7", + "@babel/types": "^7.14.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/@babel/traverse/node_modules/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, + "engines": { + "node": ">=4" + } + }, + "../node_modules/@babel/traverse/node_modules/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 + }, + "../node_modules/@babel/types": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "../node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/@eslint/eslintrc/node_modules/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 + }, + "../node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/@glimmer/env": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz", + "integrity": "sha1-/S0rVakCnGs3psk16MiHGucN+gc=", + "dev": true + }, + "../node_modules/@glimmer/interfaces": { + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.56.2.tgz", + "integrity": "sha512-nRgcsTuyZ90aEoCuYVHKGDs3LpAv9n/JKiJ6iecpEYtyGgcPqSI3GjrJRl6k+1s5wnldEH1kjWq+ccCiXmA99w==", + "dev": true, + "dependencies": { + "@simple-dom/interface": "^1.4.0" + } + }, + "../node_modules/@glimmer/syntax": { + "version": "0.56.1", + "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.56.1.tgz", + "integrity": "sha512-4TdtIQVFo9UfIVzXnXpMuzsA4mX06oF9NER8FmIPjBosNiQsYB7P8sABSG+2rtWgsh6CkFXkwvxZ++BB+alwOw==", + "dev": true, + "dependencies": { + "@glimmer/interfaces": "^0.56.1", + "@glimmer/util": "^0.56.1", + "handlebars": "^4.7.4", + "simple-html-tokenizer": "^0.5.9" + } + }, + "../node_modules/@glimmer/util": { + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.56.2.tgz", + "integrity": "sha512-AljXCX5HBjJkmNt4DNYmJmVvwqKjFF4lU6e0SBftwhzK85RbETYwpb3YWrghcjSCxoodwIu1zNFiKOA+xD6txw==", + "dev": true, + "dependencies": { + "@glimmer/env": "0.1.7", + "@glimmer/interfaces": "^0.56.2", + "@simple-dom/interface": "^1.4.0" + } + }, + "../node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "../node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/@humanwhocodes/config-array/node_modules/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 + }, + "../node_modules/@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "../node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true + }, + "../node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/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, + "engines": { + "node": ">=6" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@jest/types": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/@jsbits/deep-clone": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jsbits/deep-clone/-/deep-clone-1.1.1.tgz", + "integrity": "sha512-aKhOhRv18tlhkjapBrcyAt8U1SmyzKi2QoO4GGMlXRfQhwm7USDSo/pX8MgB8tYB3MLaevuvwufynKSDA7U3EA==", + "dev": true, + "engines": { + "node": ">=4.2" + } + }, + "../node_modules/@microsoft/api-extractor": { + "version": "7.18.1", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.18.1.tgz", + "integrity": "sha512-qljUF2Q0zAx1vJrjKkJVGN7OVbsXki+Pji99jywyl6L/FK3YZ7PpstUJYE6uBcLPy6rhNPWPAsHNTMpG/kHIsg==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor-model": "7.13.3", + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.39.0", + "@rushstack/rig-package": "0.2.12", + "@rushstack/ts-command-line": "4.8.0", + "colors": "~1.2.1", + "lodash": "~4.17.15", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "source-map": "~0.6.1", + "typescript": "~4.3.2" + }, + "bin": { + "api-extractor": "bin/api-extractor" + } + }, + "../node_modules/@microsoft/api-extractor-model": { + "version": "7.13.3", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.13.3.tgz", + "integrity": "sha512-uXilAhu2GcvyY/0NwVRk3AN7TFYjkPnjHLV2UywTTz9uglS+Af0YjNrCy+aaK8qXtfbFWdBzkH9N2XU8/YBeRQ==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.39.0" + } + }, + "../node_modules/@microsoft/api-extractor/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/@microsoft/tsdoc": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", + "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "dev": true + }, + "../node_modules/@microsoft/tsdoc-config": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", + "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "../node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/@octokit/auth-token": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.5.tgz", + "integrity": "sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "../node_modules/@octokit/core": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.0", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "../node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "../node_modules/@octokit/graphql": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.4.tgz", + "integrity": "sha512-SWTdXsVheRmlotWNjKzPOb6Js6tjSqA2a8z9+glDJng0Aqjzti8MEWOtuT8ZSu6wHnci7LZNuarE87+WJBG4vg==", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "../node_modules/@octokit/openapi-types": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-8.2.1.tgz", + "integrity": "sha512-BJz6kWuL3n+y+qM8Pv+UGbSxH6wxKf/SBs5yzGufMHwDefsa+Iq7ZGy1BINMD2z9SkXlIzk1qiu988rMuGXEMg==" + }, + "../node_modules/@octokit/plugin-paginate-rest": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.14.0.tgz", + "integrity": "sha512-S2uEu2uHeI7Vf+Lvj8tv3O5/5TCAa8GHS0dUQN7gdM7vKA6ZHAbR6HkAVm5yMb1mbedLEbxOuQ+Fa0SQ7tCDLA==", + "dependencies": { + "@octokit/types": "^6.18.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "../node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "../node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.4.1.tgz", + "integrity": "sha512-Nx0g7I5ayAYghsLJP4Q1Ch2W9jYYM0FlWWWZocUro8rNxVwuZXGfFd7Rcqi9XDWepSXjg1WByiNJnZza2hIOvQ==", + "dependencies": { + "@octokit/types": "^6.18.1", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "../node_modules/@octokit/request": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.0.tgz", + "integrity": "sha512-4cPp/N+NqmaGQwbh3vUsYqokQIzt7VjsgTYVXiwpUP2pxd5YiZB2XuTedbb0SPtv9XS7nzAKjAuQxmY8/aZkiA==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" + } + }, + "../node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "../node_modules/@octokit/rest": { + "version": "18.6.7", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.6.7.tgz", + "integrity": "sha512-Kn6WrI2ZvmAztdx+HEaf88RuJn+LK72S8g6OpciE4kbZddAN84fu4fiPGxcEu052WmqKVnA/cnQsbNlrYC6rqQ==", + "dependencies": { + "@octokit/core": "^3.5.0", + "@octokit/plugin-paginate-rest": "^2.6.2", + "@octokit/plugin-request-log": "^1.0.2", + "@octokit/plugin-rest-endpoint-methods": "5.4.1" + } + }, + "../node_modules/@octokit/types": { + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.18.1.tgz", + "integrity": "sha512-5YsddjO1U+xC8ZYKV8yZYebW55PCc7qiEEeZ+wZRr6qyclynzfyD65KZ5FdtIeP0/cANyFaD7hV69qElf1nMsQ==", + "dependencies": { + "@octokit/openapi-types": "^8.2.1" + } + }, + "../node_modules/@rushstack/node-core-library": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.39.0.tgz", + "integrity": "sha512-kgu3+7/zOBkZU0+NdJb1rcHcpk3/oTjn5c8cg5nUTn+JDjEw58yG83SoeJEcRNNdl11dGX0lKG2PxPsjCokZOQ==", + "dev": true, + "dependencies": { + "@types/node": "10.17.13", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~3.18.3" + } + }, + "../node_modules/@rushstack/node-core-library/node_modules/@types/node": { + "version": "10.17.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz", + "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==", + "dev": true + }, + "../node_modules/@rushstack/node-core-library/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "../node_modules/@rushstack/node-core-library/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/@rushstack/rig-package": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.2.12.tgz", + "integrity": "sha512-nbePcvF8hQwv0ql9aeQxcaMPK/h1OLAC00W7fWCRWIvD2MchZOE8jumIIr66HGrfG2X1sw++m/ZYI4D+BM5ovQ==", + "dev": true, + "dependencies": { + "resolve": "~1.17.0", + "strip-json-comments": "~3.1.1" + } + }, + "../node_modules/@rushstack/rig-package/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/@rushstack/ts-command-line": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.8.0.tgz", + "integrity": "sha512-nZ8cbzVF1VmFPfSJfy8vEohdiFAH/59Y/Y+B4nsJbn4SkifLJ8LqNZ5+LxCC2UR242EXFumxlsY1d6fPBxck5Q==", + "dev": true, + "dependencies": { + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "colors": "~1.2.1", + "string-argv": "~0.3.1" + } + }, + "../node_modules/@simple-dom/interface": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@simple-dom/interface/-/interface-1.4.0.tgz", + "integrity": "sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA==", + "dev": true + }, + "../node_modules/@sindresorhus/is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", + "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "../node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "../node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "../node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "../node_modules/@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "../node_modules/@sosuisen/api-documenter": { + "version": "7.13.27", + "resolved": "https://registry.npmjs.org/@sosuisen/api-documenter/-/api-documenter-7.13.27.tgz", + "integrity": "sha512-Y3uEwBRSbxEvlLXRD/YcaRhsVNVWMDRLE/EOVDAUzPYy5FrdXiNK0GZNdmxrjCe2E58W/bGKUTZnw9sOI2YOZg==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor-model": "^7.13.3", + "@microsoft/tsdoc": "^0.13.2", + "@rushstack/node-core-library": "^3.39.0", + "@rushstack/ts-command-line": "^4.7.10", + "colors": "~1.2.1", + "js-yaml": "~3.13.1", + "resolve": "~1.17.0" + }, + "bin": { + "api-documenter": "bin/api-documenter" + } + }, + "../node_modules/@sosuisen/jsondiffpatch": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@sosuisen/jsondiffpatch/-/jsondiffpatch-0.4.7.tgz", + "integrity": "sha512-PBux/ylEnBMhB5WSee+Ql2YPrO5K7YEnfSm5aZufOEkmewkduakSWdmSrmreUGmJKQWLWqRGSpql3tl7YlppTQ==", + "dependencies": { + "chalk": "^2.3.0", + "diff-match-patch": "^1.0.0" + }, + "bin": { + "jsondiffpatch": "bin/jsondiffpatch" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "../node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "../node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "../node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "../node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "../node_modules/@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true + }, + "../node_modules/@types/async-lock": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.1.3.tgz", + "integrity": "sha512-UpeDcjGKsYEQMeqEbfESm8OWJI305I7b9KE4ji3aBjoKWyN5CTdn8izcA1FM1DVDne30R5fNEnIy89vZw5LXJQ==", + "dev": true + }, + "../node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "../node_modules/@types/fs-extra": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz", + "integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "../node_modules/@types/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "../node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "../node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "dev": true + }, + "../node_modules/@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, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "../node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "../node_modules/@types/json-schema": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", + "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "dev": true + }, + "../node_modules/@types/keyv": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", + "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "dependencies": { + "@types/node": "*" + } + }, + "../node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "../node_modules/@types/mocha": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", + "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", + "dev": true + }, + "../node_modules/@types/node": { + "version": "14.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.5.tgz", + "integrity": "sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==" + }, + "../node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "../node_modules/@types/parse-git-config": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/parse-git-config/-/parse-git-config-3.0.1.tgz", + "integrity": "sha512-cBVLXlpIpP23p+jQm8d2TrTfxyub3aiqfqgd0TWRnMqwCJMskYiveNJT11YwN+gbo3+0ZFFmtaepKzN7pxExlA==", + "dev": true + }, + "../node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "../node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "../node_modules/@types/rimraf": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.1.tgz", + "integrity": "sha512-CAoSlbco40aKZ0CkelBF2g3JeN6aioRaTVnqSX5pWsn/WApm6IDxI4e4tD9D0dY/meCkyyleP1IQDVN13F4maA==", + "dev": true, + "dependencies": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "../node_modules/@types/sinon": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.11.tgz", + "integrity": "sha512-PwP4UY33SeeVKodNE37ZlOsR9cReypbMJOhZ7BVE0lB+Hix3efCOxiJWiE5Ia+yL9Cn2Ch72EjFTRze8RZsNtg==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "../node_modules/@types/sinonjs__fake-timers": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.3.tgz", + "integrity": "sha512-E1dU4fzC9wN2QK2Cr1MLCfyHM8BoNnRFvuf45LYMPNDA+WqbNzC45S4UzPxvp1fFJ1rvSGU0bPvdd35VLmXG8g==", + "dev": true + }, + "../node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "../node_modules/@types/unist": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.5.tgz", + "integrity": "sha512-wnra4Vw9dopnuybR6HBywJ/URYpYrKLoepBTEtgfJup8Ahoi2zJECPP2cwiXp7btTvOT2CULv87aQRA4eZSP6g==", + "dev": true + }, + "../node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "../node_modules/@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true + }, + "../node_modules/@typescript-eslint/eslint-plugin": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz", + "integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "4.28.2", + "@typescript-eslint/scope-manager": "4.28.2", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^4.0.0", + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "../node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/@typescript-eslint/eslint-plugin/node_modules/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 + }, + "../node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/@typescript-eslint/experimental-utils": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz", + "integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "../node_modules/@typescript-eslint/parser": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz", + "integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "../node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/@typescript-eslint/parser/node_modules/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 + }, + "../node_modules/@typescript-eslint/scope-manager": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz", + "integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "../node_modules/@typescript-eslint/types": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz", + "integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==", + "dev": true, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "../node_modules/@typescript-eslint/typescript-estree": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz", + "integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "../node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/@typescript-eslint/typescript-estree/node_modules/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 + }, + "../node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/@typescript-eslint/visitor-keys": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz", + "integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.28.2", + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "../node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "../node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "../node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "../node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "../node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "../node_modules/angular-estree-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/angular-estree-parser/-/angular-estree-parser-1.3.1.tgz", + "integrity": "sha512-jvlnNk4aoEmA6EKK12OnsOkCSdsWleBsYB+aWyH8kpfTB6Li1kxWVbHKVldH9zDCwVVi1hXfqPi/gbSv49tkbQ==", + "dev": true, + "dependencies": { + "lines-and-columns": "^1.1.6", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "@angular/compiler": ">= 6.0.0 < 9.0.6" + } + }, + "../node_modules/angular-html-parser": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-1.7.0.tgz", + "integrity": "sha512-/yjeqDQXGblZuFMI6vpDgiIDuv816QpIqa/mCotc0I4R0F5t5sfX1ntZ8VsBVQOUYRjPw8ggYlPZto76gHtf7Q==", + "dev": true, + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/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==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "../node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "../node_modules/are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "../node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "../node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "../node_modules/array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/array.prototype.flatmap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", + "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "../node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "../node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/async-lock": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.3.0.tgz", + "integrity": "sha512-8A7SkiisnEgME2zEedtDYPxUPzdv3x//E7n5IFktPAtMYSEAV7eNJF0rMwrVyUFj6d/8rgajLantbjcNRQYXIg==" + }, + "../node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "../node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "../node_modules/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=", + "engines": { + "node": "*" + } + }, + "../node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "../node_modules/bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "../node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "../node_modules/before-after-hook": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + }, + "../node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "../node_modules/blob-polyfill": { + "version": "5.0.20210201", + "resolved": "https://registry.npmjs.org/blob-polyfill/-/blob-polyfill-5.0.20210201.tgz", + "integrity": "sha512-SrH6IG6aXL9pCgSysBCiDpGcAJ1j6/c1qCwR3sTEQJhb+MTk6FITNA6eW6WNYQDNZVi4Z9GjxH5v2MMTv59CrQ==" + }, + "../node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "../node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "../node_modules/browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "../node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "../node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "../node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "../node_modules/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==" + }, + "../node_modules/cacheable-lookup": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz", + "integrity": "sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==", + "dependencies": { + "@types/keyv": "^3.1.1", + "keyv": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/caniuse-lite": { + "version": "1.0.30001243", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001243.tgz", + "integrity": "sha512-vNxw9mkTBtkmLFnJRv/2rhs1yufpDfCkBZexG3Y0xdOH2Z/eE/85E4Dl5j1YUN34nZVsSp6vVRFQRrez9wJMRA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "../node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "../node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "../node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "../node_modules/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 + }, + "../node_modules/cjk-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cjk-regex/-/cjk-regex-2.0.0.tgz", + "integrity": "sha512-E4gFi2f3jC0zFVHpaAcupW+gv9OejZ2aV3DP/LlSO0dDcZJAXw7W0ivn+vN17edN/PhU4HCgs1bfx7lPK7FpdA==", + "dev": true, + "dependencies": { + "regexp-util": "^1.2.1", + "unicode-regex": "^2.0.0" + }, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/cjk-regex/node_modules/unicode-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-2.0.0.tgz", + "integrity": "sha512-5nbEG2YU7loyTvPABaKb+8B0u8L7vWCsVmCSsiaO249ZdMKlvrXlxR2ex4TUVAdzv/Cne/TdoXSSaJArGXaleQ==", + "dev": true, + "dependencies": { + "regexp-util": "^1.2.0" + }, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==" + }, + "../node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "../node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/cliui/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "../node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "../node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/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==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "../node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "../node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "../node_modules/colors": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", + "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "../node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "../node_modules/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 + }, + "../node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "../node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "../node_modules/confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true + }, + "../node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "../node_modules/contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "../node_modules/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=" + }, + "../node_modules/cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/coveralls": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", + "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" + }, + "bin": { + "coveralls": "bin/coveralls.js" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "dependencies": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + }, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "../node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "../node_modules/crlf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/crlf/-/crlf-1.1.1.tgz", + "integrity": "sha1-JBcoQbTINSmmqkSJ337tlYsu0W8=", + "dev": true, + "dependencies": { + "glub": "^1.0.0", + "transform-file": "^1.0.1" + }, + "bin": { + "crlf": "bin/crlf" + } + }, + "../node_modules/cross-blob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cross-blob/-/cross-blob-2.0.1.tgz", + "integrity": "sha512-ARuKPPo3I6DSqizal4UCyMCiGPQdMpMJS3Owx6Lleuh26vSt2UnfWRwbMLCYqbJUrcol+KzGVSLR91ezSHP80A==", + "dependencies": { + "blob-polyfill": "^5.0.20210201", + "fetch-blob": "^2.1.2" + }, + "engines": { + "node": "^10.17.0 || >=12.3.0" + } + }, + "../node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "../node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "../node_modules/dashify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "../node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/decompress-response": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", + "integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "../node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "../node_modules/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 + }, + "../node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/default-require-extensions/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "../node_modules/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, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "../node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "../node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "../node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "../node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "../node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "../node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + }, + "../node_modules/diff-sequences": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha1-1OXDpM305f4SEatC5pP8tDIVgPw=" + }, + "../node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "../node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "../node_modules/editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "dependencies": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "bin": { + "editorconfig": "bin/editorconfig" + } + }, + "../node_modules/editorconfig-to-prettier": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/editorconfig-to-prettier/-/editorconfig-to-prettier-0.1.1.tgz", + "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==", + "dev": true + }, + "../node_modules/editorconfig/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "../node_modules/editorconfig/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "../node_modules/editorconfig/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "../node_modules/electron-to-chromium": { + "version": "1.3.772", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.772.tgz", + "integrity": "sha512-X/6VRCXWALzdX+RjCtBU6cyg8WZgoxm9YA02COmDOiNJEZ59WkQggDbWZ4t/giHi/3GS+cvdrP6gbLISANAGYA==", + "dev": true + }, + "../node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "../node_modules/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==", + "dependencies": { + "once": "^1.4.0" + } + }, + "../node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "../node_modules/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, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "../node_modules/es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/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, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "../node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/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=", + "engines": { + "node": ">=0.8.0" + } + }, + "../node_modules/eslint": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz", + "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "../node_modules/eslint-ast-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz", + "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==", + "dev": true, + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.zip": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/eslint-config-prettier": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", + "dev": true, + "dependencies": { + "get-stdin": "^6.0.0" + }, + "bin": { + "eslint-config-prettier-check": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=3.14.1" + } + }, + "../node_modules/eslint-config-standard": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^7.12.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1 || ^5.0.0" + } + }, + "../node_modules/eslint-config-standardize": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/eslint-config-standardize/-/eslint-config-standardize-0.7.2.tgz", + "integrity": "sha512-n2dt7la221Qig7FjQsrKn5NyK5jSEkkAy7xWSnY96XdG7H9FcUSDt5I1THyA6zHwEYcAtUFv8VOPBOK6oYEvfg==", + "dev": true, + "dependencies": { + "@jsbits/deep-clone": "~1.1.1", + "confusing-browser-globals": "*", + "deepmerge": "~4.2.2", + "eslint-config-standard": "~16.0.2", + "eslint-plugin-import": "~2.22.1", + "eslint-plugin-node": "~11.1.0", + "eslint-plugin-promise": "~4.2.1", + "eslint-plugin-react": "~7.22.0", + "eslint-plugin-react-hooks": "~4.2.0", + "eslint-plugin-unicorn": "~26.0.1" + }, + "bin": { + "list-eslint-config": "bin/list-eslint-config.js" + }, + "engines": { + "node": "^10.13.0 || >=12.0.0" + }, + "optionalDependencies": { + "@typescript-eslint/eslint-plugin": "^4.14.0", + "@typescript-eslint/parser": "^4.14.0" + }, + "peerDependencies": { + "eslint": ">=7.17.0" + } + }, + "../node_modules/eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "dependencies": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + } + }, + "../node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "../node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "../node_modules/eslint-module-utils": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", + "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "pkg-dir": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "../node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "../node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" + } + }, + "../node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "../node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "../node_modules/eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "../node_modules/eslint-plugin-node/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "../node_modules/eslint-plugin-node/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../node_modules/eslint-plugin-prettierx": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettierx/-/eslint-plugin-prettierx-0.14.0.tgz", + "integrity": "sha512-Ak/sI2LO0B73qEFjepPNUplxLadqpT3BU/I16ExZ0mY1CjpjoJxiyKe7Nbb0VEH4XO4SbjhngGPSsod+S3/HPA==", + "dev": true, + "dependencies": { + "eslint-config-prettier": "~6.11.0", + "prettier-linter-helpers": "~1.0.0", + "prettierx": "~0.14.0" + }, + "bin": { + "list-eslint-config": "bin/list-eslint-config.js" + }, + "engines": { + "node": "^10.13.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.2.0", + "typescript": ">=3.8.0" + } + }, + "../node_modules/eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/eslint-plugin-react": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7" + } + }, + "../node_modules/eslint-plugin-react-hooks": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", + "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "../node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/eslint-plugin-unicorn": { + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-26.0.1.tgz", + "integrity": "sha512-SWgF9sIVY74zqkkSN2dclSCqRfocWSUGD0haC0NX2oRfmdp9p8dQvJYkYSQePaCyssPUE/pqpsIEEZNTh8crUA==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0", + "clean-regexp": "^1.0.0", + "eslint-ast-utils": "^1.1.0", + "eslint-template-visitor": "^2.2.2", + "eslint-utils": "^2.1.0", + "import-modules": "^2.1.0", + "lodash": "^4.17.20", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.21", + "reserved-words": "^0.1.2", + "safe-regex": "^2.1.1", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=7.17.0" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/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, + "engines": { + "node": ">=6" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/eslint-plugin-unicorn/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "../node_modules/eslint-template-visitor": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz", + "integrity": "sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", + "eslint-visitor-keys": "^2.0.0", + "esquery": "^1.3.1", + "multimap": "^1.1.0" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "../node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "../node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "../node_modules/eslint/node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "../node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/eslint/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/eslint/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/eslint/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "../node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/eslint/node_modules/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 + }, + "../node_modules/eslint/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/eslint/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "../node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "../node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "engines": { + "node": ">=0.8" + } + }, + "../node_modules/expect": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.6.tgz", + "integrity": "sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.0.6", + "ansi-styles": "^5.0.0", + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-regex-util": "^27.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/expect/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "../node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "../node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "../node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "../node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/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==" + }, + "../node_modules/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 + }, + "../node_modules/fastq": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", + "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "../node_modules/fetch-blob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz", + "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==", + "engines": { + "node": "^10.17.0 || >=12.3.0" + }, + "peerDependenciesMeta": { + "domexception": { + "optional": true + } + } + }, + "../node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "../node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "../node_modules/find-cache-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/find-cache-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/find-cache-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/find-cache-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/find-cache-dir/node_modules/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, + "engines": { + "node": ">=6" + } + }, + "../node_modules/find-cache-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "../node_modules/find-project-root": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/find-project-root/-/find-project-root-1.1.1.tgz", + "integrity": "sha1-0kJyei2QRyXfVxTyPf3N7doLbvg=", + "dev": true, + "bin": { + "find-project-root": "bin/find-project-root.js" + } + }, + "../node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "../node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "../node_modules/flatted": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", + "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==", + "dev": true + }, + "../node_modules/flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", + "dev": true + }, + "../node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "../node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "../node_modules/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==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "../node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "../node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "../node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/fs-extra/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "../node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "../node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "../node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "../node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "../node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "../node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "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" + } + }, + "../node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "../node_modules/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, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "../node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "../node_modules/get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "../node_modules/git-config-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-2.0.0.tgz", + "integrity": "sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/git-documentdb-plugin-remote-nodegit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-documentdb-plugin-remote-nodegit/-/git-documentdb-plugin-remote-nodegit-1.0.3.tgz", + "integrity": "sha512-80cxPE+jIjDpECCXAmNtjZxMFVNc38yFkZmEd3hRp6EvSQhX6nky0kmEFWZ1aeFnTq0oATEJvEJg9yO8zYkyng==", + "dependencies": { + "git-documentdb-remote-errors": "^1.0.3", + "nodegit": "^0.27.0", + "tslog": "^3.2.0" + } + }, + "../node_modules/git-documentdb-remote-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-documentdb-remote-errors/-/git-documentdb-remote-errors-1.0.3.tgz", + "integrity": "sha512-14fN8VAQeBC7+Phs6TYB1D5PJDE/dF8dxbigKpsBEqR1FvpAQerSPptxVsQgkU33xwwZBOm7yCwVD2KKmQatOQ==" + }, + "../node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/globals": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", + "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/glub": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/glub/-/glub-1.0.3.tgz", + "integrity": "sha1-VsFkMpiuJQZcYxUAMze7pp0vuGY=", + "dev": true, + "dependencies": { + "glob": "^5.0.5", + "minimist": "^1.1.1" + }, + "bin": { + "glub": "bin/glub" + } + }, + "../node_modules/glub/node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "../node_modules/got": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", + "integrity": "sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==", + "dependencies": { + "@sindresorhus/is": "^2.0.0", + "@szmarczak/http-timer": "^4.0.0", + "@types/cacheable-request": "^6.0.1", + "cacheable-lookup": "^2.0.0", + "cacheable-request": "^7.0.1", + "decompress-response": "^5.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "../node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "../node_modules/graphql": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz", + "integrity": "sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "../node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "../node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "../node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "../node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "../node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "../node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "../node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "../node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "../node_modules/html-element-attributes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/html-element-attributes/-/html-element-attributes-2.2.1.tgz", + "integrity": "sha512-gGTgCeQu+g1OFExZKWQ1LwbFXxLJ6cGdCGj64ByEaxatr/EPVc23D6Gxngb37ao+SNInP/sGu8FXxRsSxMm7aQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "../node_modules/html-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/html-styles/-/html-styles-1.0.0.tgz", + "integrity": "sha1-oYBh/WUfmca3XEXI4FSaO8PgGnU=", + "dev": true + }, + "../node_modules/html-tag-names": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/html-tag-names/-/html-tag-names-1.1.5.tgz", + "integrity": "sha512-aI5tKwNTBzOZApHIynaAwecLBv8TlZTEy/P4Sj2SzzAhBrGuI8yGZ0UIXVPQzOHGS+to2mjb04iy6VWt/8+d8A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "../node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "../node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "engines": { + "node": ">= 4" + } + }, + "../node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "../node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/import-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "../node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "../node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "../node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "../node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "../node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "../node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "../node_modules/is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "../node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "../node_modules/is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "../node_modules/is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "../node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "../node_modules/isomorphic-git": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.9.1.tgz", + "integrity": "sha512-vzceJaiBdaJI5aT1di4dxWWf6sao3WQFQJ6UTi1tXO4zyDfsuyIadVOA4YQzdwKhLilV9msgM8HIvpOE94kmQg==", + "dependencies": { + "async-lock": "^1.1.0", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^3.4.0", + "sha.js": "^2.4.9", + "simple-get": "^3.0.2" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/isomorphic-git/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "../node_modules/istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../node_modules/istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/istanbul-lib-source-maps/node_modules/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 + }, + "../node_modules/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/jest-diff": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", + "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "../node_modules/jest-get-type": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/jest-matcher-utils": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz", + "integrity": "sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/jest-message-util": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.0.6", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "pretty-format": "^27.0.6", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/jest-regex-util": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, + "../node_modules/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 + }, + "../node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "../node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "../node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "../node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "../node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "../node_modules/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==" + }, + "../node_modules/json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "../node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "../node_modules/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=" + }, + "../node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "../node_modules/jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "engines": { + "node": "*" + } + }, + "../node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "../node_modules/jsx-ast-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", + "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.2", + "object.assign": "^4.1.2" + }, + "engines": { + "node": ">=4.0" + } + }, + "../node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "../node_modules/keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "../node_modules/lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true, + "bin": { + "lcov-parse": "bin/cli.js" + } + }, + "../node_modules/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, + "engines": { + "node": ">=6" + } + }, + "../node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "../node_modules/linguist-languages": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-7.10.0.tgz", + "integrity": "sha512-Uqt94P4iAznscZtccnNE1IBi105U+fmQKEUlDJv54JDdFZDInomkepEIRpZLOQcPyGdcNu3JO9Tvo5wpQVbfKw==", + "dev": true + }, + "../node_modules/load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "../node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "../node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "../node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "../node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "../node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "../node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "../node_modules/lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "dev": true + }, + "../node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true, + "engines": { + "node": ">=0.8.6" + } + }, + "../node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/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, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "../node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "../node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/lru-cache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "../node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../node_modules/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 + }, + "../node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/mem": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.1.tgz", + "integrity": "sha512-Ci6bIfq/UgcxPTYa8dQQ5FY3BzKkT894bwXWXxC/zqs0XgMO2cT20CGkOqda7gZNkmK5VP4x89IGZ6K7hfbn3Q==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "../node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "../node_modules/mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "engines": { + "node": ">= 0.6" + } + }, + "../node_modules/mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "dependencies": { + "mime-db": "1.48.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "../node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "../node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "../node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "dependencies": { + "minimist": "^1.2.5" + } + }, + "../node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "../node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "../node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "../node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "../node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "../node_modules/mocha/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/mocha/node_modules/debug/node_modules/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 + }, + "../node_modules/mocha/node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "../node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/mocha/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/mocha/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "../node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/mocha/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "../node_modules/mocha/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "../node_modules/multimap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", + "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==", + "dev": true + }, + "../node_modules/n-readlines": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/n-readlines/-/n-readlines-1.0.1.tgz", + "integrity": "sha512-z4SyAIVgMy7CkgsoNw7YVz40v0g4+WWvvqy8+ZdHrCtgevcEO758WQyrYcw3XPxcLxF+//RszTz/rO48nzD0wQ==", + "dev": true, + "engines": { + "node": ">=6.x.x" + } + }, + "../node_modules/nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" + }, + "../node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "../node_modules/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 + }, + "../node_modules/needle": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz", + "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "../node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "../node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "../node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "../node_modules/node-gyp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-4.0.0.tgz", + "integrity": "sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA==", + "dependencies": { + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^4.4.8", + "which": "1" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "../node_modules/node-gyp/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "../node_modules/node-gyp/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/node-pre-gyp": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz", + "integrity": "sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "dependencies": { + "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" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "../node_modules/node-pre-gyp/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "../node_modules/node-pre-gyp/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "../node_modules/node-pre-gyp/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "../node_modules/node-pre-gyp/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "../node_modules/node-pre-gyp/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "../node_modules/node-pre-gyp/node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "../node_modules/node-pre-gyp/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "../node_modules/node-pre-gyp/node_modules/tar": { + "version": "4.4.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.15.tgz", + "integrity": "sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==", + "dependencies": { + "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" + }, + "engines": { + "node": ">=4.5" + } + }, + "../node_modules/node-pre-gyp/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "../node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/node-releases": { + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "dev": true + }, + "../node_modules/nodegit": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/nodegit/-/nodegit-0.27.0.tgz", + "integrity": "sha512-E9K4gPjWiA0b3Tx5lfWCzG7Cvodi2idl3V5UD2fZrOrHikIfrN7Fc2kWLtMUqqomyoToYJLeIC8IV7xb1CYRLA==", + "hasInstallScript": true, + "dependencies": { + "fs-extra": "^7.0.0", + "got": "^10.7.0", + "json5": "^2.1.0", + "lodash": "^4.17.14", + "nan": "^2.14.0", + "node-gyp": "^4.0.0", + "node-pre-gyp": "^0.13.0", + "ramda": "^0.25.0", + "tar-fs": "^1.16.3" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/nodegit/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "../node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "../node_modules/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, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "../node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "../node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "../node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "../node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "../node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "../node_modules/nyc/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/nyc/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "../node_modules/nyc/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/nyc/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/nyc/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/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, + "engines": { + "node": ">=6" + } + }, + "../node_modules/nyc/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "../node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "../node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/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, + "engines": { + "node": ">= 0.4" + } + }, + "../node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/object.entries": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.4.tgz", + "integrity": "sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "../node_modules/object.fromentries": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", + "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/object.values": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "../node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "../node_modules/ot-json1": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ot-json1/-/ot-json1-1.0.2.tgz", + "integrity": "sha512-IhxkqVWQqlkWULoi/Q2AdzKk0N5vQRbUMUwubFXFCPcY4TsOZjmp2YKrk0/z1TeiECPadWEK060sdFdQ3Grokg==", + "dependencies": { + "ot-text-unicode": "4" + } + }, + "../node_modules/ot-text-unicode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ot-text-unicode/-/ot-text-unicode-4.0.0.tgz", + "integrity": "sha512-W7ZLU8QXesY2wagYFv47zErXud3E93FGImmSGJsQnBzE+idcPPyo2u2KMilIrTwBh4pbCizy71qRjmmV6aDhcQ==", + "dependencies": { + "unicount": "1.1" + } + }, + "../node_modules/ot-text-unicode/node_modules/unicount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicount/-/unicount-1.1.0.tgz", + "integrity": "sha512-RlwWt1ywVW4WErPGAVHw/rIuJ2+MxvTME0siJ6lk9zBhpDfExDbspe6SRlWT3qU6AucNjotPl9qAJRVjP7guCQ==" + }, + "../node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "../node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dependencies": { + "p-timeout": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, + "../node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "../node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "../node_modules/parse-git-config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-3.0.0.tgz", + "integrity": "sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA==", + "dev": true, + "dependencies": { + "git-config-path": "^2.0.0", + "ini": "^1.3.5" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/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, + "engines": { + "node": ">=4" + } + }, + "../node_modules/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=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "../node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "../node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "../node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "../node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "../node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "../node_modules/pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "../node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/postcss": { + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "../node_modules/postcss-less": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz", + "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "../node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "../node_modules/postcss-scss": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz", + "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../node_modules/postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "../node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dev": true, + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "../node_modules/postcss/node_modules/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, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../node_modules/prettierx": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/prettierx/-/prettierx-0.14.3.tgz", + "integrity": "sha512-0VT3GgDAU6rvemeklrRzqVkILrGC1TSo/4STnsBqkreLx5Ck43W05lO60pMKWbG7SWM3DcUZZIR4FZ5pvvDwyQ==", + "dev": true, + "dependencies": { + "@angular/compiler": "9.0.5", + "@babel/code-frame": "7.12.11", + "@babel/parser": "7.12.0", + "@glimmer/syntax": "0.56.1", + "@iarna/toml": "2.2.5", + "@typescript-eslint/typescript-estree": "2.34.0", + "angular-estree-parser": "1.3.1", + "angular-html-parser": "1.7.0", + "camelcase": "6.2.0", + "chalk": "4.1.0", + "ci-info": "2.0.0", + "cjk-regex": "2.0.0", + "cosmiconfig": "7.0.0", + "dashify": "2.0.0", + "dedent": "0.7.0", + "diff": "4.0.2", + "editorconfig": "0.15.3", + "editorconfig-to-prettier": "0.1.1", + "escape-string-regexp": "4.0.0", + "esutils": "2.0.3", + "fast-glob": "3.2.4", + "find-parent-dir": "0.3.0", + "find-project-root": "1.1.1", + "get-stream": "6.0.0", + "globby": "11.0.1", + "graphql": "15.3.0", + "html-element-attributes": "2.2.1", + "html-styles": "1.0.0", + "html-tag-names": "1.1.5", + "ignore": "4.0.6", + "jest-docblock": "26.0.0", + "json-stable-stringify": "1.0.1", + "leven": "3.1.0", + "lines-and-columns": "1.1.6", + "linguist-languages": "7.10.0", + "lodash": "4.17.20", + "mem": "6.1.1", + "minimatch": "3.0.4", + "minimist": "1.2.5", + "n-readlines": "1.0.1", + "please-upgrade-node": "3.2.0", + "postcss-less": "3.1.4", + "postcss-media-query-parser": "0.2.3", + "postcss-scss": "2.1.1", + "postcss-selector-parser": "2.2.3", + "postcss-values-parser": "2.0.1", + "regexp-util": "1.2.2", + "remark-math": "1.0.6", + "remark-parse": "5.0.0", + "resolve": "1.19.0", + "semver": "7.3.4", + "srcset": "3.0.0", + "string-width": "4.2.0", + "tslib": "1.14.1", + "unicode-regex": "3.0.0", + "unified": "9.2.0", + "vnopts": "1.0.2", + "yaml-unist-parser": "1.3.1" + }, + "bin": { + "prettierx": "bin/prettierx.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependenciesMeta": { + "flow-parser": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "../node_modules/prettierx/node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "../node_modules/prettierx/node_modules/@babel/parser": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.0.tgz", + "integrity": "sha512-dYmySMYnlus2jwl7JnnajAj11obRStZoW9cG04wh4ZuhozDn11tDUrhHcUZ9iuNHqALAhh60XqNaYXpvuuE/Gg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../node_modules/prettierx/node_modules/@typescript-eslint/typescript-estree": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", + "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "../node_modules/prettierx/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/prettierx/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/prettierx/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../node_modules/prettierx/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/prettierx/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/prettierx/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "../node_modules/prettierx/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/prettierx/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/prettierx/node_modules/fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/prettierx/node_modules/get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/prettierx/node_modules/globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/prettierx/node_modules/globby/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/prettierx/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/prettierx/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/prettierx/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/prettierx/node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "../node_modules/prettierx/node_modules/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 + }, + "../node_modules/prettierx/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/prettierx/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/prettierx/node_modules/string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/prettierx/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/prettierx/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/pretty-format": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.0.6", + "ansi-regex": "^5.0.0", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "../node_modules/pretty-format/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "../node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "../node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "../node_modules/prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "../node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "../node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "../node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "../node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "../node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "../node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "../node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "../node_modules/ramda": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", + "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==" + }, + "../node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "../node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "../node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "../node_modules/read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "dependencies": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/read-pkg/node_modules/path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "dependencies": { + "pify": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/read-pkg/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "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" + } + }, + "../node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "../node_modules/regexp-tree": { + "version": "0.1.23", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.23.tgz", + "integrity": "sha512-+7HWfb4Bvu8Rs2eQTUIpX9I/PlQkYOuTNbRpKLJlQpSgwSkzFYh+pUj0gtvglnOZLKB6YgnIgRuJ2/IlpL48qw==", + "dev": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "../node_modules/regexp-util": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/regexp-util/-/regexp-util-1.2.2.tgz", + "integrity": "sha512-5/rl2UD18oAlLQEIuKBeiSIOp1hb5wCXcakl5yvHxlY1wyWI4D5cUKKzCibBeu741PA9JKvZhMqbkDQqPusX3w==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "../node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/remark-math": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-1.0.6.tgz", + "integrity": "sha512-I43wU/QOQpXvVFXKjA4FHp5xptK65+5F6yolm8+69/JV0EqSOB64wURUZ3JK50JtnTL8FvwLiH2PZ+fvsBxviA==", + "dev": true, + "dependencies": { + "trim-trailing-lines": "^1.1.0" + }, + "peerDependencies": { + "remark-parse": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + } + }, + "../node_modules/remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, + "dependencies": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "../node_modules/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, + "engines": { + "node": ">=0.10" + } + }, + "../node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/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 + }, + "../node_modules/reserved-words": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", + "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", + "dev": true + }, + "../node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "../node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "../node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "../node_modules/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==" + }, + "../node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, + "../node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "../node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "../node_modules/semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "bin": { + "semver": "bin/semver" + } + }, + "../node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "../node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "../node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "../node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "../node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "../node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "../node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "../node_modules/simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "../node_modules/simple-get/node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/simple-html-tokenizer": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz", + "integrity": "sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og==", + "dev": true + }, + "../node_modules/sinon": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.1.0", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "../node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "../node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "../node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/spawn-wrap/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "../node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "../node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "../node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "../node_modules/spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "dev": true + }, + "../node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "../node_modules/srcset": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-3.0.0.tgz", + "integrity": "sha512-D59vF08Qzu/C4GAOXVgMTLfgryt5fyWo93FZyhEWANo0PokFz/iWdDe13mX3O5TRf6l8vMTqckAfR4zPiaH0yQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "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" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "../node_modules/string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "../node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/string.prototype.matchall": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz", + "integrity": "sha512-Z5ZaXO0svs0M2xd/6By3qpeKpLKd9mO4v4q3oMEQrk8Ck4xOD5d5XeBOOjGrmVZZ/AHB1S0CgG4N5r1G9N3E2Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../node_modules/table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "../node_modules/table/node_modules/ajv": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz", + "integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "../node_modules/table/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "../node_modules/table/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/table/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/tar": { + "version": "4.4.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.15.tgz", + "integrity": "sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==", + "dependencies": { + "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" + }, + "engines": { + "node": ">=4.5" + } + }, + "../node_modules/tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "dependencies": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + } + }, + "../node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "../node_modules/tar-fs/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "../node_modules/tar-fs/node_modules/pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "../node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "../node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "../node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "../node_modules/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, + "engines": { + "node": ">=4" + } + }, + "../node_modules/to-readable-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==", + "engines": { + "node": ">=8" + } + }, + "../node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "../node_modules/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==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "../node_modules/transform-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/transform-file/-/transform-file-1.0.1.tgz", + "integrity": "sha1-f5WYSs0j1Ov4q7R+6dg74WbRJoc=", + "dev": true, + "dependencies": { + "os-tmpdir": "^1.0.0" + } + }, + "../node_modules/trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "../node_modules/trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/ts-node": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", + "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", + "dev": true, + "dependencies": { + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "../node_modules/tsconfig-paths": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz", + "integrity": "sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==", + "dev": true, + "dependencies": { + "json5": "^2.2.0", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "../node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "../node_modules/tslog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.2.0.tgz", + "integrity": "sha512-xOCghepl5w+wcI4qXI7vJy6c53loF8OoC/EuKz1ktAPMtltEDz00yo1poKuyBYIQaq4ZDYKYFPD9PfqVrFXh0A==", + "dependencies": { + "source-map-support": "^0.5.19" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "../node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "../node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "../node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../node_modules/type-fest": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "../node_modules/typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "../node_modules/uglify-js": { + "version": "3.13.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.10.tgz", + "integrity": "sha512-57H3ACYFXeo1IaZ1w02sfA71wI60MGco/IQFjOqK+WtKoprh7Go2/yvd2HPtoJILO2Or84ncLccI4xoHMTSbGg==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "../node_modules/ulid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", + "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", + "bin": { + "ulid": "bin/cli.js" + } + }, + "../node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "../node_modules/unicode-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-3.0.0.tgz", + "integrity": "sha512-WiDJdORsqgxkZrjC8WsIP573130HNn7KsB0IDnUccW2BG2b19QQNloNhVe6DKk3Aef0UcoIHhNVj7IkkcYWrNw==", + "dev": true, + "dependencies": { + "regexp-util": "^1.2.0" + }, + "engines": { + "node": ">= 4" + } + }, + "../node_modules/unicount": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicount/-/unicount-1.2.0.tgz", + "integrity": "sha512-bbM0gwaKyIPll7smeeufgbN9sbJbrtr29o93HqF+4bzTeQcTN4zKtBKGwnLoGSG+E6gPQ/WL0t7xAhPKnWW4mQ==" + }, + "../node_modules/unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dev": true, + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "../node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "../node_modules/unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true + }, + "../node_modules/unist-util-remove-position": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", + "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "dev": true, + "dependencies": { + "unist-util-visit": "^1.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "../node_modules/unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "../node_modules/unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, + "dependencies": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "../node_modules/unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, + "dependencies": { + "unist-util-is": "^3.0.0" + } + }, + "../node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "../node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "../node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "../node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "../node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "../node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "../node_modules/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, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "../node_modules/validator": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz", + "integrity": "sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "../node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "../node_modules/vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "../node_modules/vfile-location": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "../node_modules/vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "../node_modules/vnopts": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vnopts/-/vnopts-1.0.2.tgz", + "integrity": "sha512-d2rr2EFhAGHnTlURu49G7GWmiJV80HbAnkYdD9IFAtfhmxC+kSWEaZ6ZF064DJFTv9lQZQV1vuLTntyQpoanGQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "leven": "^2.1.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/vnopts/node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "../node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../node_modules/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 + }, + "../node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "../node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "../node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "../node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "../node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "../node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "../node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "../node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "../node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "../node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "../node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/yaml-unist-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/yaml-unist-parser/-/yaml-unist-parser-1.3.1.tgz", + "integrity": "sha512-4aHBMpYcnByF8l2OKj5hlBJlxSYIMON8Z1Hm57ymbBL4omXMlGgY+pEf4Di6h2qNT8ZG8seTVvAQYNOa7CZ9eA==", + "dev": true, + "dependencies": { + "lines-and-columns": "^1.1.6", + "tslib": "^1.10.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">= 6" + } + }, + "../node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "../node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "../node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../node_modules/yargs/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../node_modules/z-schema": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.18.4.tgz", + "integrity": "sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw==", + "dev": true, + "dependencies": { + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^8.0.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "optionalDependencies": { + "commander": "^2.7.1" + } + }, + "node_modules/@sindresorhus/is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", + "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sosuisen/nodegit": { + "version": "0.28.0-alpha.11", + "resolved": "https://registry.npmjs.org/@sosuisen/nodegit/-/nodegit-0.28.0-alpha.11.tgz", + "integrity": "sha512-mpztf9ncWxU7/agKQ6E7GvlBIa6H7m3YXuMjlPWVegHusqkbgPi4J01d2inCPhLz0CoC0F/L3LKJuDCAKDXJJg==", + "hasInstallScript": true, + "dependencies": { + "fs-extra": "^7.0.0", + "got": "^10.7.0", + "json5": "^2.1.0", + "lodash": "^4.17.14", + "nan": "^2.14.1", + "node-gyp": "^7.1.2", + "node-pre-gyp": "^0.13.0", + "ramda": "^0.25.0", + "tar-fs": "^1.16.3" + }, + "engines": { + "node": ">= 12.19.0 < 13 || >= 14.10.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "node_modules/@types/keyv": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", + "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "16.4.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz", + "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg==" + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/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=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/cacheable-lookup": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz", + "integrity": "sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==", + "dependencies": { + "@types/keyv": "^3.1.1", + "keyv": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/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=" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decompress-response": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", + "integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/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==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/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==" + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/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==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "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" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/git-documentdb": { + "resolved": "..", + "link": true + }, + "node_modules/git-documentdb-plugin-remote-nodegit": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/git-documentdb-plugin-remote-nodegit/-/git-documentdb-plugin-remote-nodegit-1.0.4.tgz", + "integrity": "sha512-+esXlN6PMmvwKZPU6dn/kSQnVe5QHU9xGzoNrLiqehz+VM1AXgNhsce/KipimG4wdzUS6tbS9QbgIgA4VjpbAw==", + "dependencies": { + "@sosuisen/nodegit": "^0.28.0-alpha.11", + "git-documentdb-remote-errors": "^1.0.3", + "tslog": "^3.2.0" + } + }, + "node_modules/git-documentdb-remote-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-documentdb-remote-errors/-/git-documentdb-remote-errors-1.0.3.tgz", + "integrity": "sha512-14fN8VAQeBC7+Phs6TYB1D5PJDE/dF8dxbigKpsBEqR1FvpAQerSPptxVsQgkU33xwwZBOm7yCwVD2KKmQatOQ==" + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/got": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", + "integrity": "sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==", + "dependencies": { + "@sindresorhus/is": "^2.0.0", + "@szmarczak/http-timer": "^4.0.0", + "@types/cacheable-request": "^6.0.1", + "cacheable-lookup": "^2.0.0", + "cacheable-request": "^7.0.1", + "decompress-response": "^5.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/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==" + }, + "node_modules/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=" + }, + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mime-db": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "dependencies": { + "mime-db": "1.49.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "node_modules/needle": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz", + "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-pre-gyp": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz", + "integrity": "sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "dependencies": { + "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" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/node-pre-gyp/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/node-pre-gyp/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/node-pre-gyp/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/node-pre-gyp/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/node-pre-gyp/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/node-pre-gyp/node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/node-pre-gyp/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/node-pre-gyp/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-pre-gyp/node_modules/tar": { + "version": "4.4.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.15.tgz", + "integrity": "sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==", + "dependencies": { + "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" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/node-pre-gyp/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dependencies": { + "p-timeout": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ramda": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", + "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "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" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/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==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "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" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz", + "integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "dependencies": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/tar-fs/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/tar-fs/node_modules/pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "node_modules/to-readable-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tslog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.2.0.tgz", + "integrity": "sha512-xOCghepl5w+wcI4qXI7vJy6c53loF8OoC/EuKz1ktAPMtltEDz00yo1poKuyBYIQaq4ZDYKYFPD9PfqVrFXh0A==", + "dependencies": { + "source-map-support": "^0.5.19" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/type-fest": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", + "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, "dependencies": { + "@sindresorhus/is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", + "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==" + }, + "@sosuisen/nodegit": { + "version": "0.28.0-alpha.11", + "resolved": "https://registry.npmjs.org/@sosuisen/nodegit/-/nodegit-0.28.0-alpha.11.tgz", + "integrity": "sha512-mpztf9ncWxU7/agKQ6E7GvlBIa6H7m3YXuMjlPWVegHusqkbgPi4J01d2inCPhLz0CoC0F/L3LKJuDCAKDXJJg==", + "requires": { + "fs-extra": "^7.0.0", + "got": "^10.7.0", + "json5": "^2.1.0", + "lodash": "^4.17.14", + "nan": "^2.14.1", + "node-gyp": "^7.1.2", + "node-pre-gyp": "^0.13.0", + "ramda": "^0.25.0", + "tar-fs": "^1.16.3" + } + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "@types/keyv": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", + "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "16.4.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz", + "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg==" + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "requires": { + "@types/node": "*" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "cacheable-lookup": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz", + "integrity": "sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==", + "requires": { + "@types/keyv": "^3.1.1", + "keyv": "^4.0.0" + } + }, + "cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "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=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "decompress-response": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", + "integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "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==", + "requires": { + "once": "^1.4.0" + } + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "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==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "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" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "git-documentdb": { "version": "file:..", "requires": { + "@microsoft/api-extractor": "^7.16.0", "@octokit/rest": "^18.3.5", + "@octokit/types": "^6.12.2", + "@sosuisen/api-documenter": "^7.13.27", "@sosuisen/jsondiffpatch": "^0.4.7", - "@sosuisen/nodegit": "^0.27.3", "@types/async-lock": "^1.1.2", + "@types/fs-extra": "^9.0.12", + "@types/js-yaml": "^4.0.3", + "@types/mocha": "^8.2.2", + "@types/node": "^14.14.20", + "@types/parse-git-config": "^3.0.0", + "@types/rimraf": "^3.0.0", + "@types/sinon": "^9.0.11", + "@typescript-eslint/eslint-plugin": "^4.28.0", + "@typescript-eslint/parser": "^4.28.0", "async-lock": "^1.3.0", + "coveralls": "^3.1.0", + "crlf": "^1.1.1", "cross-blob": "^2.0.0", + "cross-env": "^7.0.3", + "eslint": "^7.17.0", + "eslint-config-standardize": "^0.7.1", + "eslint-plugin-prettierx": "^0.14.0", + "eslint-plugin-unicorn": "^36.0.0", + "expect": "^27.0.2", "fs-extra": "^9.1.0", - "isomorphic-git": "^1.8.2", + "git-documentdb-plugin-remote-nodegit": "^1.0.4", + "git-documentdb-remote-errors": "^1.0.3", + "hmtid": "^0.1.0", + "isomorphic-git": "^1.17.1", + "js-yaml": "^4.1.0", + "mocha": "^8.3.2", + "nyc": "^15.1.0", "ot-json1": "^1.0.2", + "parse-git-config": "^3.0.0", "rimraf": "^3.0.2", + "sinon": "^10.0.0", + "ts-node": "^10.1.0", + "tsconfig-paths": "^3.9.0", "tslog": "^3.1.2", + "typescript": "^4.3.4", "ulid": "^2.3.0", "unicount": "^1.2.0" }, @@ -25,51 +12516,103 @@ "@angular/compiler": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.5.tgz", - "integrity": "sha512-TeyhRGefTOtA9N3udMrvheafoXcz/dvTTdZLcieeZQxm1SSeaQDUQ/rUH6QTOiHVNMtjOCrZ9J5rk1A4mPYuag==" + "integrity": "sha512-TeyhRGefTOtA9N3udMrvheafoXcz/dvTTdZLcieeZQxm1SSeaQDUQ/rUH6QTOiHVNMtjOCrZ9J5rk1A4mPYuag==", + "dev": true, + "requires": {} }, "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.14.5" } }, + "@babel/compat-data": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "dev": true + }, "@babel/core": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", - "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.10", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.10", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz", + "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helpers": "^7.14.6", + "@babel/parser": "^7.14.6", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "lodash": "^4.17.19", - "semver": "^5.4.1", + "semver": "^6.3.0", "source-map": "^0.5.0" }, "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/eslint-parser": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.14.7.tgz", + "integrity": "sha512-6WPwZqO5priAGIwV6msJcdc9TsEPzYeYdS/Xuoap+/ihkgN6dzHp2bcAAwyWZ5bLzk0vvjDmKvRwkqNaiJ8BiQ==", + "dev": true, + "requires": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.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 } } }, "@babel/generator": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", - "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "dev": true, "requires": { - "@babel/types": "^7.12.11", + "@babel/types": "^7.14.5", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -77,248 +12620,291 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.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 } } }, "@babel/helper-function-name": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", - "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/types": "^7.12.11" + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/helper-get-function-arity": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", - "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "dev": true, "requires": { - "@babel/types": "^7.12.10" + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", - "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "dev": true, "requires": { - "@babel/types": "^7.12.7" + "@babel/types": "^7.14.5" } }, "@babel/helper-module-imports": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", - "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "dev": true, "requires": { - "@babel/types": "^7.12.5" + "@babel/types": "^7.14.5" } }, "@babel/helper-module-transforms": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", - "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", + "dev": true, "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-simple-access": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/helper-validator-identifier": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "lodash": "^4.17.19" + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/helper-optimise-call-expression": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", - "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "dev": true, "requires": { - "@babel/types": "^7.12.10" + "@babel/types": "^7.14.5" } }, "@babel/helper-replace-supers": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", - "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.7", - "@babel/helper-optimise-call-expression": "^7.12.10", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.11" + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/helper-simple-access": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", - "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", + "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.14.5" } }, "@babel/helper-split-export-declaration": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", - "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "dev": true, "requires": { - "@babel/types": "^7.12.11" + "@babel/types": "^7.14.5" } }, "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true }, "@babel/helpers": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", - "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", + "dev": true, "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.5", - "@babel/types": "^7.12.5" + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.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==", - "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=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } } }, "@babel/parser": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", - "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==" + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "dev": true }, "@babel/template": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", - "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.12.7", - "@babel/types": "^7.12.7" + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" } }, "@babel/traverse": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", - "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", - "requires": { - "@babel/code-frame": "^7.12.11", - "@babel/generator": "^7.12.11", - "@babel/helper-function-name": "^7.12.11", - "@babel/helper-split-export-declaration": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/types": "^7.12.12", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/parser": "^7.14.7", + "@babel/types": "^7.14.5", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" + "globals": "^11.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "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.12.12", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", - "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.12.11", - "lodash": "^4.17.19", + "@babel/helper-validator-identifier": "^7.14.5", "to-fast-properties": "^2.0.0" } }, "@eslint/eslintrc": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", - "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", "espree": "^7.3.0", - "globals": "^12.1.0", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.19", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { - "type-fest": "^0.8.1" + "ms": "2.1.2" } }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "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 + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true } } }, "@glimmer/env": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz", - "integrity": "sha1-/S0rVakCnGs3psk16MiHGucN+gc=" + "integrity": "sha1-/S0rVakCnGs3psk16MiHGucN+gc=", + "dev": true }, "@glimmer/interfaces": { - "version": "0.56.1", - "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.56.1.tgz", - "integrity": "sha512-+0KvSd7c9QmkEeCFHaBDub1DBeTONw+x6MZUcb/MlA3FfNis2aFs7kHVkjkdzp0Ust54Wn448dgWZFW27EuVJA==", + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.56.2.tgz", + "integrity": "sha512-nRgcsTuyZ90aEoCuYVHKGDs3LpAv9n/JKiJ6iecpEYtyGgcPqSI3GjrJRl6k+1s5wnldEH1kjWq+ccCiXmA99w==", + "dev": true, "requires": { "@simple-dom/interface": "^1.4.0" } @@ -327,6 +12913,7 @@ "version": "0.56.1", "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.56.1.tgz", "integrity": "sha512-4TdtIQVFo9UfIVzXnXpMuzsA4mX06oF9NER8FmIPjBosNiQsYB7P8sABSG+2rtWgsh6CkFXkwvxZ++BB+alwOw==", + "dev": true, "requires": { "@glimmer/interfaces": "^0.56.1", "@glimmer/util": "^0.56.1", @@ -335,65 +12922,220 @@ } }, "@glimmer/util": { - "version": "0.56.1", - "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.56.1.tgz", - "integrity": "sha512-g7R5hMtZ2BLF+AsYhSE1xoh0gOJALof4/JL6zovYvqrsKTLYGK1Qe3RKXSt8dPav8Ac0LXt+cOd6jHPGSrEs+A==", + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.56.2.tgz", + "integrity": "sha512-AljXCX5HBjJkmNt4DNYmJmVvwqKjFF4lU6e0SBftwhzK85RbETYwpb3YWrghcjSCxoodwIu1zNFiKOA+xD6txw==", + "dev": true, "requires": { "@glimmer/env": "0.1.7", - "@glimmer/interfaces": "^0.56.1", + "@glimmer/interfaces": "^0.56.2", "@simple-dom/interface": "^1.4.0" } }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, "@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, "requires": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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 + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } } }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==" + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true }, "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", + "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", + "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^16.0.0", "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "@jsbits/deep-clone": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@jsbits/deep-clone/-/deep-clone-1.1.1.tgz", - "integrity": "sha512-aKhOhRv18tlhkjapBrcyAt8U1SmyzKi2QoO4GGMlXRfQhwm7USDSo/pX8MgB8tYB3MLaevuvwufynKSDA7U3EA==" + "integrity": "sha512-aKhOhRv18tlhkjapBrcyAt8U1SmyzKi2QoO4GGMlXRfQhwm7USDSo/pX8MgB8tYB3MLaevuvwufynKSDA7U3EA==", + "dev": true }, "@microsoft/api-extractor": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.16.0.tgz", - "integrity": "sha512-6CIpg4Iw4DWJszZMwYhh8OQ0bsmKq6CFjeCHfciDzmV+cUJ8ysJrO4LhYKNHEMOcfUYIv0EVoYul7/zMXTv9eA==", + "version": "7.18.1", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.18.1.tgz", + "integrity": "sha512-qljUF2Q0zAx1vJrjKkJVGN7OVbsXki+Pji99jywyl6L/FK3YZ7PpstUJYE6uBcLPy6rhNPWPAsHNTMpG/kHIsg==", + "dev": true, "requires": { - "@microsoft/api-extractor-model": "7.13.2", + "@microsoft/api-extractor-model": "7.13.3", "@microsoft/tsdoc": "0.13.2", "@microsoft/tsdoc-config": "~0.15.2", - "@rushstack/node-core-library": "3.38.0", + "@rushstack/node-core-library": "3.39.0", "@rushstack/rig-package": "0.2.12", - "@rushstack/ts-command-line": "4.7.10", + "@rushstack/ts-command-line": "4.8.0", "colors": "~1.2.1", "lodash": "~4.17.15", "resolve": "~1.17.0", @@ -402,75 +13144,14 @@ "typescript": "~4.3.2" }, "dependencies": { - "@microsoft/api-extractor-model": { - "version": "7.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.13.2.tgz", - "integrity": "sha512-gA9Q8q5TPM2YYk7rLinAv9KqcodrmRC13BVmNzLswjtFxpz13lRh0BmrqD01/sddGpGMIuWFYlfUM4VSWxnggA==", - "requires": { - "@microsoft/tsdoc": "0.13.2", - "@microsoft/tsdoc-config": "~0.15.2", - "@rushstack/node-core-library": "3.38.0" - } - }, - "@rushstack/node-core-library": { - "version": "3.38.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.38.0.tgz", - "integrity": "sha512-cmvl0yQx8sSmbuXwiRYJi8TO+jpTtrLJQ8UmFHhKvgPVJAW8cV8dnpD1Xx/BvTGrJZ2XtRAIkAhBS9okBnap4w==", - "requires": { - "@types/node": "10.17.13", - "colors": "~1.2.1", - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.17.0", - "semver": "~7.3.0", - "timsort": "~0.3.0", - "z-schema": "~3.18.3" - } - }, - "@types/node": { - "version": "10.17.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz", - "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==" - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } - }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" } } }, @@ -478,6 +13159,7 @@ "version": "7.13.3", "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.13.3.tgz", "integrity": "sha512-uXilAhu2GcvyY/0NwVRk3AN7TFYjkPnjHLV2UywTTz9uglS+Af0YjNrCy+aaK8qXtfbFWdBzkH9N2XU8/YBeRQ==", + "dev": true, "requires": { "@microsoft/tsdoc": "0.13.2", "@microsoft/tsdoc-config": "~0.15.2", @@ -487,12 +13169,14 @@ "@microsoft/tsdoc": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", - "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==" + "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "dev": true }, "@microsoft/tsdoc-config": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "dev": true, "requires": { "@microsoft/tsdoc": "0.13.2", "ajv": "~6.12.6", @@ -500,33 +13184,41 @@ "resolve": "~1.19.0" }, "dependencies": { - "@microsoft/tsdoc": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", - "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==" + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } } } }, "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.4", + "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.4", + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, @@ -539,13 +13231,13 @@ } }, "@octokit/core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.3.0.tgz", - "integrity": "sha512-GGMpjaodCBY7JrtOwfolMocwZw9Pj5NxuQqfaJhGau4tkyonm0JRV9D6juQYLMb1Kl261++4Q980o0FlAtg8jg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", "requires": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.4.12", + "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.0.5", "@octokit/types": "^6.0.3", "before-after-hook": "^2.2.0", @@ -553,85 +13245,70 @@ } }, "@octokit/endpoint": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", - "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", "requires": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - } } }, "@octokit/graphql": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.1.tgz", - "integrity": "sha512-2lYlvf4YTDgZCTXTW4+OX+9WTLFtEUc6hGm4qM1nlZjzxj+arizM4aHWzBVBCxY9glh7GIs0WEuiSgbVzv8cmA==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.4.tgz", + "integrity": "sha512-SWTdXsVheRmlotWNjKzPOb6Js6tjSqA2a8z9+glDJng0Aqjzti8MEWOtuT8ZSu6wHnci7LZNuarE87+WJBG4vg==", "requires": { - "@octokit/request": "^5.3.0", + "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.3.2.tgz", - "integrity": "sha512-NxF1yfYOUO92rCx3dwvA2onF30Vdlg7YUkMVXkeptqpzA3tRLplThhFleV/UKWFgh7rpKu1yYRbvNDUtzSopKA==" + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-8.2.1.tgz", + "integrity": "sha512-BJz6kWuL3n+y+qM8Pv+UGbSxH6wxKf/SBs5yzGufMHwDefsa+Iq7ZGy1BINMD2z9SkXlIzk1qiu988rMuGXEMg==" }, "@octokit/plugin-paginate-rest": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.11.0.tgz", - "integrity": "sha512-7L9xQank2G3r1dGqrVPo1z62V5utbykOUzlmNHPz87Pww/JpZQ9KyG5CHtUzgmB4n5iDRKYNK/86A8D98HP0yA==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.14.0.tgz", + "integrity": "sha512-S2uEu2uHeI7Vf+Lvj8tv3O5/5TCAa8GHS0dUQN7gdM7vKA6ZHAbR6HkAVm5yMb1mbedLEbxOuQ+Fa0SQ7tCDLA==", "requires": { - "@octokit/types": "^6.11.0" + "@octokit/types": "^6.18.0" } }, "@octokit/plugin-request-log": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", - "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "4.13.5", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.5.tgz", - "integrity": "sha512-kYKcWkFm4Ldk8bZai2RVEP1z97k1C/Ay2FN9FNTBg7JIyKoiiJjks4OtT6cuKeZX39tqa+C3J9xeYc6G+6g8uQ==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.4.1.tgz", + "integrity": "sha512-Nx0g7I5ayAYghsLJP4Q1Ch2W9jYYM0FlWWWZocUro8rNxVwuZXGfFd7Rcqi9XDWepSXjg1WByiNJnZza2hIOvQ==", "requires": { - "@octokit/types": "^6.12.2", + "@octokit/types": "^6.18.1", "deprecation": "^2.3.1" } }, "@octokit/request": { - "version": "5.4.14", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.14.tgz", - "integrity": "sha512-VkmtacOIQp9daSnBmDI92xNIeLuSRDOIuplp/CJomkvzt7M18NXgG044Cx/LFKLgjKt9T2tZR6AtJayba9GTSA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.0.tgz", + "integrity": "sha512-4cPp/N+NqmaGQwbh3vUsYqokQIzt7VjsgTYVXiwpUP2pxd5YiZB2XuTedbb0SPtv9XS7nzAKjAuQxmY8/aZkiA==", "requires": { "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.0.0", - "@octokit/types": "^6.7.1", - "deprecation": "^2.0.0", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.1", - "once": "^1.4.0", "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - } } }, "@octokit/request-error": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", - "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "requires": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -639,28 +13316,29 @@ } }, "@octokit/rest": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.5.tgz", - "integrity": "sha512-ZPeRms3WhWxQBEvoIh0zzf8xdU2FX0Capa7+lTca8YHmRsO3QNJzf1H3PcuKKsfgp91/xVDRtX91sTe1kexlbw==", + "version": "18.6.7", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.6.7.tgz", + "integrity": "sha512-Kn6WrI2ZvmAztdx+HEaf88RuJn+LK72S8g6OpciE4kbZddAN84fu4fiPGxcEu052WmqKVnA/cnQsbNlrYC6rqQ==", "requires": { - "@octokit/core": "^3.2.3", + "@octokit/core": "^3.5.0", "@octokit/plugin-paginate-rest": "^2.6.2", "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "4.13.5" + "@octokit/plugin-rest-endpoint-methods": "5.4.1" } }, "@octokit/types": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.12.2.tgz", - "integrity": "sha512-kCkiN8scbCmSq+gwdJV0iLgHc0O/GTPY1/cffo9kECu1MvatLPh9E+qFhfRIktKfHEA6ZYvv6S1B4Wnv3bi3pA==", + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.18.1.tgz", + "integrity": "sha512-5YsddjO1U+xC8ZYKV8yZYebW55PCc7qiEEeZ+wZRr6qyclynzfyD65KZ5FdtIeP0/cANyFaD7hV69qElf1nMsQ==", "requires": { - "@octokit/openapi-types": "^5.3.2" + "@octokit/openapi-types": "^8.2.1" } }, "@rushstack/node-core-library": { "version": "3.39.0", "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.39.0.tgz", "integrity": "sha512-kgu3+7/zOBkZU0+NdJb1rcHcpk3/oTjn5c8cg5nUTn+JDjEw58yG83SoeJEcRNNdl11dGX0lKG2PxPsjCokZOQ==", + "dev": true, "requires": { "@types/node": "10.17.13", "colors": "~1.2.1", @@ -676,46 +13354,28 @@ "@types/node": { "version": "10.17.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz", - "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==" + "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==", + "dev": true }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } - }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" } } }, @@ -723,25 +13383,25 @@ "version": "0.2.12", "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.2.12.tgz", "integrity": "sha512-nbePcvF8hQwv0ql9aeQxcaMPK/h1OLAC00W7fWCRWIvD2MchZOE8jumIIr66HGrfG2X1sw++m/ZYI4D+BM5ovQ==", + "dev": true, "requires": { "resolve": "~1.17.0", - "strip-json-comments": "~3.1.1" - }, - "dependencies": { - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } + "strip-json-comments": "~3.1.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true } } }, "@rushstack/ts-command-line": { - "version": "4.7.10", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.7.10.tgz", - "integrity": "sha512-8t042g8eerypNOEcdpxwRA3uCmz0duMo21rG4Z2mdz7JxJeylDmzjlU3wDdef2t3P1Z61JCdZB6fbm1Mh0zi7w==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.8.0.tgz", + "integrity": "sha512-nZ8cbzVF1VmFPfSJfy8vEohdiFAH/59Y/Y+B4nsJbn4SkifLJ8LqNZ5+LxCC2UR242EXFumxlsY1d6fPBxck5Q==", + "dev": true, "requires": { "@types/argparse": "1.0.38", "argparse": "~1.0.9", @@ -752,7 +13412,8 @@ "@simple-dom/interface": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@simple-dom/interface/-/interface-1.4.0.tgz", - "integrity": "sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA==" + "integrity": "sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA==", + "dev": true }, "@sindresorhus/is": { "version": "2.1.1", @@ -760,9 +13421,10 @@ "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==" }, "@sinonjs/commons": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", - "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, "requires": { "type-detect": "4.0.8" } @@ -771,6 +13433,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" } @@ -779,6 +13442,7 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", "lodash.get": "^4.4.2", @@ -788,12 +13452,14 @@ "@sinonjs/text-encoding": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true }, "@sosuisen/api-documenter": { - "version": "7.13.25", - "resolved": "https://registry.npmjs.org/@sosuisen/api-documenter/-/api-documenter-7.13.25.tgz", - "integrity": "sha512-/BW6yDpP9DJGUtD/KD42DQR+Od7Gje1gAnrpwotwpEGhqCzAPyzZiV5z/1eegZfWbnmvtrPSbsCAtVkAhXmLZA==", + "version": "7.13.27", + "resolved": "https://registry.npmjs.org/@sosuisen/api-documenter/-/api-documenter-7.13.27.tgz", + "integrity": "sha512-Y3uEwBRSbxEvlLXRD/YcaRhsVNVWMDRLE/EOVDAUzPYy5FrdXiNK0GZNdmxrjCe2E58W/bGKUTZnw9sOI2YOZg==", + "dev": true, "requires": { "@microsoft/api-extractor-model": "^7.13.3", "@microsoft/tsdoc": "^0.13.2", @@ -802,25 +13468,6 @@ "colors": "~1.2.1", "js-yaml": "~3.13.1", "resolve": "~1.17.0" - }, - "dependencies": { - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } - } } }, "@sosuisen/jsondiffpatch": { @@ -830,117 +13477,56 @@ "requires": { "chalk": "^2.3.0", "diff-match-patch": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.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==", - "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=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@sosuisen/nodegit": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@sosuisen/nodegit/-/nodegit-0.27.3.tgz", - "integrity": "sha512-0/SSdtXK+grdpbhJP116MtkyHWA1yJ+Tnnzsj5OEPj/bC5s9Losc52p8WKiDn1uKeJcN5F5Zg+VOx4vkBKD4dg==", - "requires": { - "fs-extra": "^7.0.0", - "got": "^10.7.0", - "json5": "^2.1.0", - "lodash": "^4.17.14", - "nan": "^2.14.0", - "node-gyp": "^4.0.0", - "node-pre-gyp": "^0.13.0", - "ramda": "^0.25.0", - "tar-fs": "^1.16.3" - }, - "dependencies": { - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - } } }, "@szmarczak/http-timer": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", - "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "requires": { "defer-to-connect": "^2.0.0" } }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, "@types/argparse": { "version": "1.0.38", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", - "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==" + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true }, "@types/async-lock": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.1.2.tgz", - "integrity": "sha512-j9n4bb6RhgFIydBe0+kpjnBPYumDaDyU8zvbWykyVMkku+c2CSu31MZkLeaBfqIwU+XCxlDpYDfyMQRkM0AkeQ==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.1.3.tgz", + "integrity": "sha512-UpeDcjGKsYEQMeqEbfESm8OWJI305I7b9KE4ji3aBjoKWyN5CTdn8izcA1FM1DVDne30R5fNEnIy89vZw5LXJQ==", + "dev": true }, "@types/cacheable-request": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", - "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", "requires": { "@types/http-cache-semantics": "*", "@types/keyv": "*", @@ -948,51 +13534,41 @@ "@types/responselike": "*" } }, - "@types/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "optional": true - }, - "@types/expect": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-24.3.0.tgz", - "integrity": "sha512-aq5Z+YFBz5o2b6Sp1jigx5nsmoZMK5Ceurjwy6PZmRv7dEi1jLtkARfvB1ME+OXJUG+7TZUDcv3WoCr/aor6dQ==", - "requires": { - "expect": "*" - } - }, "@types/fs-extra": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.6.tgz", - "integrity": "sha512-ecNRHw4clCkowNOBJH1e77nvbPxHYnWIXMv1IAoG/9+MYGkgoyr3Ppxr7XYFNL41V422EDhyV4/4SSK8L2mlig==", + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz", + "integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==", + "dev": true, "requires": { "@types/node": "*" } }, "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "dev": true, "requires": { "@types/minimatch": "*", "@types/node": "*" } }, "@types/http-cache-semantics": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", - "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==" + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "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": "*" } @@ -1001,58 +13577,59 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, "requires": { "@types/istanbul-lib-report": "*" } }, "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "optional": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", + "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "dev": true }, "@types/keyv": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", - "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", + "integrity": "sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==", "requires": { "@types/node": "*" } }, "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true }, "@types/mocha": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", - "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==" + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", + "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", + "dev": true }, "@types/node": { - "version": "14.14.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", - "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==" + "version": "14.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.5.tgz", + "integrity": "sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==" }, "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true }, "@types/parse-git-config": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-git-config/-/parse-git-config-3.0.0.tgz", - "integrity": "sha512-5C14/81ohSwjB5I0EweuG3qyn6CqgVOgk9orxHDwVvUdDbS4FMXANXnKz3CA3H2Jk2oa3vzMEpXtDQ5u0dCcTQ==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/parse-git-config/-/parse-git-config-3.0.1.tgz", + "integrity": "sha512-cBVLXlpIpP23p+jQm8d2TrTfxyub3aiqfqgd0TWRnMqwCJMskYiveNJT11YwN+gbo3+0ZFFmtaepKzN7pxExlA==", + "dev": true }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true }, "@types/responselike": { "version": "1.0.0", @@ -1063,9 +13640,10 @@ } }, "@types/rimraf": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.0.tgz", - "integrity": "sha512-7WhJ0MdpFgYQPXlF4Dx+DhgvlPCfz/x5mHaeDQAKhcenvQP1KCpLQ18JklAqeGMYSAT2PxLpzd0g2/HE7fj7hQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.1.tgz", + "integrity": "sha512-CAoSlbco40aKZ0CkelBF2g3JeN6aioRaTVnqSX5pWsn/WApm6IDxI4e4tD9D0dY/meCkyyleP1IQDVN13F4maA==", + "dev": true, "requires": { "@types/glob": "*", "@types/node": "*" @@ -1075,45 +13653,52 @@ "version": "9.0.11", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.11.tgz", "integrity": "sha512-PwP4UY33SeeVKodNE37ZlOsR9cReypbMJOhZ7BVE0lB+Hix3efCOxiJWiE5Ia+yL9Cn2Ch72EjFTRze8RZsNtg==", + "dev": true, "requires": { "@types/sinonjs__fake-timers": "*" } }, "@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.3.tgz", + "integrity": "sha512-E1dU4fzC9wN2QK2Cr1MLCfyHM8BoNnRFvuf45LYMPNDA+WqbNzC45S4UzPxvp1fFJ1rvSGU0bPvdd35VLmXG8g==", + "dev": true }, "@types/stack-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", - "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true }, "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.5.tgz", + "integrity": "sha512-wnra4Vw9dopnuybR6HBywJ/URYpYrKLoepBTEtgfJup8Ahoi2zJECPP2cwiXp7btTvOT2CULv87aQRA4eZSP6g==", + "dev": true }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "20.2.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", - "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz", - "integrity": "sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz", + "integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==", + "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.28.0", - "@typescript-eslint/scope-manager": "4.28.0", + "@typescript-eslint/experimental-utils": "4.28.2", + "@typescript-eslint/scope-manager": "4.28.2", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.1.0", @@ -1121,173 +13706,99 @@ "tsutils": "^3.21.0" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", - "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0" + "ms": "2.1.2" } }, - "@typescript-eslint/types": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", - "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==" - }, - "@typescript-eslint/visitor-keys": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", - "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", - "requires": { - "@typescript-eslint/types": "4.28.0", - "eslint-visitor-keys": "^2.0.0" - } + "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 }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "requires": { - "tslib": "^1.8.1" - } } } }, "@typescript-eslint/experimental-utils": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz", - "integrity": "sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz", + "integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==", + "dev": true, "requires": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.0", - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/typescript-estree": "4.28.0", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz", + "integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", + "debug": "^4.3.1" }, "dependencies": { - "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" - }, - "@typescript-eslint/scope-manager": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", - "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", - "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0" - } - }, - "@typescript-eslint/types": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", - "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==" - }, - "@typescript-eslint/typescript-estree": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz", - "integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==", - "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", - "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", - "requires": { - "@typescript-eslint/types": "4.28.0", - "eslint-visitor-keys": "^2.0.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { - "lru-cache": "^6.0.0" + "ms": "2.1.2" } }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "requires": { - "tslib": "^1.8.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 } } }, - "@typescript-eslint/parser": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.0.tgz", - "integrity": "sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==", - "requires": { - "@typescript-eslint/scope-manager": "4.28.0", - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/typescript-estree": "4.28.0", - "debug": "^4.3.1" - } - }, "@typescript-eslint/scope-manager": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", - "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz", + "integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0" + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2" } }, "@typescript-eslint/types": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", - "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==" + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz", + "integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==", + "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz", - "integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz", + "integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -1295,37 +13806,47 @@ "tsutils": "^3.21.0" }, "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "requires": { - "tslib": "^1.8.1" - } } } }, "@typescript-eslint/visitor-keys": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", - "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz", + "integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==", + "dev": true, "requires": { - "@typescript-eslint/types": "4.28.0", + "@typescript-eslint/types": "4.28.2", "eslint-visitor-keys": "^2.0.0" } }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true }, "abbrev": { "version": "1.1.1", @@ -1335,17 +13856,21 @@ "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true }, "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1366,6 +13891,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/angular-estree-parser/-/angular-estree-parser-1.3.1.tgz", "integrity": "sha512-jvlnNk4aoEmA6EKK12OnsOkCSdsWleBsYB+aWyH8kpfTB6Li1kxWVbHKVldH9zDCwVVi1hXfqPi/gbSv49tkbQ==", + "dev": true, "requires": { "lines-and-columns": "^1.1.6", "tslib": "^1.9.3" @@ -1375,6 +13901,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-1.7.0.tgz", "integrity": "sha512-/yjeqDQXGblZuFMI6vpDgiIDuv816QpIqa/mCotc0I4R0F5t5sfX1ntZ8VsBVQOUYRjPw8ggYlPZto76gHtf7Q==", + "dev": true, "requires": { "tslib": "^1.9.3" } @@ -1382,25 +13909,27 @@ "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "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==", "requires": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1410,6 +13939,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, "requires": { "default-require-extensions": "^3.0.0" } @@ -1422,7 +13952,8 @@ "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true }, "are-we-there-yet": { "version": "1.1.5", @@ -1436,7 +13967,8 @@ "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, "argparse": { "version": "1.0.10", @@ -1447,26 +13979,29 @@ } }, "array-includes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", - "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "get-intrinsic": "^1.0.1", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" } }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true }, "array.prototype.flat": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", @@ -1477,6 +14012,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", @@ -1500,7 +14036,8 @@ "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true }, "async-lock": { "version": "1.3.0", @@ -1527,35 +14064,16 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, - "babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" - } - } - }, "bail": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -1566,14 +14084,15 @@ } }, "before-after-hook": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.0.tgz", - "integrity": "sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true }, "bl": { "version": "1.2.3", @@ -1585,9 +14104,9 @@ } }, "blob-polyfill": { - "version": "4.0.20200601", - "resolved": "https://registry.npmjs.org/blob-polyfill/-/blob-polyfill-4.0.20200601.tgz", - "integrity": "sha512-1jB6WOIp6IDxNyng5+9A8g/f0uiphib2ELCN+XAnlssinsW8s1k4VYG9b1TxIUd3pdm9RJSLQuBh6iohYmD4hA==" + "version": "5.0.20210201", + "resolved": "https://registry.npmjs.org/blob-polyfill/-/blob-polyfill-5.0.20210201.tgz", + "integrity": "sha512-SrH6IG6aXL9pCgSysBCiDpGcAJ1j6/c1qCwR3sTEQJhb+MTk6FITNA6eW6WNYQDNZVi4Z9GjxH5v2MMTv59CrQ==" }, "brace-expansion": { "version": "1.1.11", @@ -1602,6 +14121,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -1609,7 +14129,21 @@ "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + } }, "buffer-alloc": { "version": "1.2.0", @@ -1645,33 +14179,24 @@ } }, "cacheable-request": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", - "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", + "normalize-url": "^6.0.1", "responselike": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - } } }, "caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, "requires": { "hasha": "^5.0.0", "make-dir": "^3.0.0", @@ -1680,23 +14205,32 @@ } }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "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==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001243", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001243.tgz", + "integrity": "sha512-vNxw9mkTBtkmLFnJRv/2rhs1yufpDfCkBZexG3Y0xdOH2Z/eE/85E4Dl5j1YUN34nZVsSp6vVRFQRrez9wJMRA==", + "dev": true }, "caseless": { "version": "0.12.0", @@ -1704,36 +14238,42 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "character-entities": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true }, "character-entities-legacy": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true }, "character-reference-invalid": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true }, "chokidar": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -1749,12 +14289,14 @@ "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true }, "cjk-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cjk-regex/-/cjk-regex-2.0.0.tgz", "integrity": "sha512-E4gFi2f3jC0zFVHpaAcupW+gv9OejZ2aV3DP/LlSO0dDcZJAXw7W0ivn+vN17edN/PhU4HCgs1bfx7lPK7FpdA==", + "dev": true, "requires": { "regexp-util": "^1.2.1", "unicode-regex": "^2.0.0" @@ -1764,6 +14306,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-2.0.0.tgz", "integrity": "sha512-5nbEG2YU7loyTvPABaKb+8B0u8L7vWCsVmCSsiaO249ZdMKlvrXlxR2ex4TUVAdzv/Cne/TdoXSSaJArGXaleQ==", + "dev": true, "requires": { "regexp-util": "^1.2.0" } @@ -1779,6 +14322,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=", + "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } @@ -1786,16 +14330,52 @@ "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true }, "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } } }, "clone-response": { @@ -1821,25 +14401,33 @@ "collapse-white-space": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true }, "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true }, "colors": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", - "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==" + "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", + "dev": true }, "combined-stream": { "version": "1.0.8", @@ -1852,12 +14440,14 @@ "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==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true }, "concat-map": { "version": "0.0.1", @@ -1867,7 +14457,8 @@ "confusing-browser-globals": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", - "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==" + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true }, "console-control-strings": { "version": "1.1.0", @@ -1877,12 +14468,14 @@ "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=" + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "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==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -1896,18 +14489,34 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, "requires": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" + }, + "dependencies": { + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + } } }, "coveralls": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", - "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", + "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", + "dev": true, "requires": { "js-yaml": "^3.13.1", "lcov-parse": "^1.0.0", @@ -1928,66 +14537,53 @@ "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "crlf": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/crlf/-/crlf-1.1.1.tgz", "integrity": "sha1-JBcoQbTINSmmqkSJ337tlYsu0W8=", + "dev": true, "requires": { "glub": "^1.0.0", "transform-file": "^1.0.1" } }, "cross-blob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cross-blob/-/cross-blob-2.0.0.tgz", - "integrity": "sha512-NWzFuyG4GTZnM9MtQvjPYVlO12lZCSBdoHIHCZl9WKShsK3CqO+bEH7nuKwlVomlByb37XvT6nVY5uQxDBmk5Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cross-blob/-/cross-blob-2.0.1.tgz", + "integrity": "sha512-ARuKPPo3I6DSqizal4UCyMCiGPQdMpMJS3Owx6Lleuh26vSt2UnfWRwbMLCYqbJUrcol+KzGVSLR91ezSHP80A==", "requires": { - "blob-polyfill": "^4.0.20200601", - "fetch-blob": "^2.0.1" + "blob-polyfill": "^5.0.20210201", + "fetch-blob": "^2.1.2" } }, "cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, "requires": { "cross-spawn": "^7.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -2005,20 +14601,22 @@ "dashify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", - "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==" + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", + "dev": true }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.1" } }, "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true }, "decompress-response": { "version": "5.0.0", @@ -2031,7 +14629,8 @@ "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true }, "deep-extend": { "version": "0.6.0", @@ -2041,30 +14640,42 @@ "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=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true }, "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, "requires": { "strip-bom": "^4.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + } } }, "defer-to-connect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", - "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" }, "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" } @@ -2092,12 +14703,14 @@ "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true }, "diff-match-patch": { "version": "1.0.5", @@ -2105,9 +14718,10 @@ "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" }, "diff-sequences": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", - "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==" + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", + "dev": true }, "diff3": { "version": "0.0.3", @@ -2118,6 +14732,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "requires": { "path-type": "^4.0.0" } @@ -2126,6 +14741,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "requires": { "esutils": "^2.0.2" } @@ -2148,6 +14764,7 @@ "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, "requires": { "commander": "^2.19.0", "lru-cache": "^4.1.5", @@ -2159,27 +14776,43 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true } } }, "editorconfig-to-prettier": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/editorconfig-to-prettier/-/editorconfig-to-prettier-0.1.1.tgz", - "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==" + "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.772", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.772.tgz", + "integrity": "sha512-X/6VRCXWALzdX+RjCtBU6cyg8WZgoxm9YA02COmDOiNJEZ59WkQggDbWZ4t/giHi/3GS+cvdrP6gbLISANAGYA==", + "dev": true }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "end-of-stream": { "version": "1.4.4", @@ -2193,6 +14826,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, "requires": { "ansi-colors": "^4.1.1" } @@ -2201,33 +14835,40 @@ "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.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.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", @@ -2237,12 +14878,14 @@ "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", @@ -2250,28 +14893,32 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz", - "integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==", + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz", + "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==", + "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.2", + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -2279,7 +14926,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -2288,101 +14935,141 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^6.0.4", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@babel/highlight": "^7.10.4" } }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "type-fest": "^0.8.1" + "color-convert": "^2.0.1" } }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "color-name": "~1.1.4" } }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "ms": "2.1.2" } }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + "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 }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "requires": { - "prelude-ls": "^1.2.1" - } + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "isexe": "^2.0.0" + "has-flag": "^4.0.0" } } } @@ -2391,6 +15078,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz", "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==", + "dev": true, "requires": { "lodash.get": "^4.4.2", "lodash.zip": "^4.2.0" @@ -2400,127 +15088,43 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", + "dev": true, "requires": { "get-stdin": "^6.0.0" } }, "eslint-config-standard": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz", - "integrity": "sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==" + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", + "dev": true, + "requires": {} }, "eslint-config-standardize": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/eslint-config-standardize/-/eslint-config-standardize-0.7.1.tgz", - "integrity": "sha512-8tut4nppZ+kpOHPa/AG8Wzr/HAEmNGnJXrGa10dCBKmNGaBsXtLkYL1hb1s80EGyw1JchIyHOpy/z9vHWeqAeQ==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/eslint-config-standardize/-/eslint-config-standardize-0.7.2.tgz", + "integrity": "sha512-n2dt7la221Qig7FjQsrKn5NyK5jSEkkAy7xWSnY96XdG7H9FcUSDt5I1THyA6zHwEYcAtUFv8VOPBOK6oYEvfg==", + "dev": true, "requires": { "@jsbits/deep-clone": "~1.1.1", - "@typescript-eslint/eslint-plugin": "~3.9.0", - "@typescript-eslint/parser": "~3.9.0", + "@typescript-eslint/eslint-plugin": "^4.14.0", + "@typescript-eslint/parser": "^4.14.0", "confusing-browser-globals": "*", "deepmerge": "~4.2.2", - "eslint-config-standard": "~14.1.1", - "eslint-plugin-import": "~2.22.0", + "eslint-config-standard": "~16.0.2", + "eslint-plugin-import": "~2.22.1", "eslint-plugin-node": "~11.1.0", "eslint-plugin-promise": "~4.2.1", - "eslint-plugin-react": "~7.20.5", - "eslint-plugin-react-hooks": "~4.0.8", - "eslint-plugin-standard": "~4.0.1", - "eslint-plugin-unicorn": "~21.0.0" - }, - "dependencies": { - "@typescript-eslint/eslint-plugin": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.9.1.tgz", - "integrity": "sha512-XIr+Mfv7i4paEdBf0JFdIl9/tVxyj+rlilWIfZ97Be0lZ7hPvUbS5iHt9Glc8kRI53dsr0PcAEudbf8rO2wGgg==", - "optional": true, - "requires": { - "@typescript-eslint/experimental-utils": "3.9.1", - "debug": "^4.1.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.1.tgz", - "integrity": "sha512-lkiZ8iBBaYoyEKhCkkw4SAeatXyBq9Ece5bZXdLe1LWBUwTszGbmbiqmQbwWA8cSYDnjWXp9eDbXpf9Sn0hLAg==", - "optional": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/types": "3.9.1", - "@typescript-eslint/typescript-estree": "3.9.1", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - } - }, - "@typescript-eslint/parser": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.9.1.tgz", - "integrity": "sha512-y5QvPFUn4Vl4qM40lI+pNWhTcOWtpZAJ8pOEQ21fTTW4xTJkRplMjMRje7LYTXqVKKX9GJhcyweMz2+W1J5bMg==", - "optional": true, - "requires": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.9.1", - "@typescript-eslint/types": "3.9.1", - "@typescript-eslint/typescript-estree": "3.9.1", - "eslint-visitor-keys": "^1.1.0" - } - }, - "@typescript-eslint/types": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.9.1.tgz", - "integrity": "sha512-15JcTlNQE1BsYy5NBhctnEhEoctjXOjOK+Q+rk8ugC+WXU9rAcS2BYhoh6X4rOaXJEpIYDl+p7ix+A5U0BqPTw==", - "optional": true - }, - "@typescript-eslint/typescript-estree": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.1.tgz", - "integrity": "sha512-IqM0gfGxOmIKPhiHW/iyAEXwSVqMmR2wJ9uXHNdFpqVvPaQ3dWg302vW127sBpAiqM9SfHhyS40NKLsoMpN2KA==", - "optional": true, - "requires": { - "@typescript-eslint/types": "3.9.1", - "@typescript-eslint/visitor-keys": "3.9.1", - "debug": "^4.1.1", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.1.tgz", - "integrity": "sha512-zxdtUjeoSh+prCpogswMwVUJfEFmCOjdzK9rpNjNBfm6EyPt99x3RrJoBOGZO23FCt0WPKUCOL5mb/9D5LjdwQ==", - "optional": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "optional": true - }, - "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "optional": true, - "requires": { - "lru-cache": "^6.0.0" - } - } + "eslint-plugin-react": "~7.22.0", + "eslint-plugin-react-hooks": "~4.2.0", + "eslint-plugin-unicorn": "~26.0.1" } }, "eslint-import-resolver-node": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, "requires": { "debug": "^2.6.9", "resolve": "^1.13.1" @@ -2530,6 +15134,7 @@ "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" } @@ -2537,205 +15142,93 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", + "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "dev": true, "requires": { - "debug": "^2.6.9", + "debug": "^3.2.7", "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "requires": { - "find-up": "^2.1.0" - } - } } }, "eslint-plugin-es": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, "requires": { "eslint-utils": "^2.0.0", "regexpp": "^3.0.0" - } - }, - "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", - "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { + "eslint-utils": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "eslint-visitor-keys": "^1.1.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "p-limit": { + "eslint-visitor-keys": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { - "pify": "^2.0.0" + "ms": "2.0.0" } }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, - "read-pkg-up": { + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -2743,6 +15236,7 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, "requires": { "eslint-plugin-es": "^3.0.0", "eslint-utils": "^2.0.0", @@ -2752,10 +15246,26 @@ "semver": "^6.1.0" }, "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -2763,6 +15273,7 @@ "version": "0.14.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettierx/-/eslint-plugin-prettierx-0.14.0.tgz", "integrity": "sha512-Ak/sI2LO0B73qEFjepPNUplxLadqpT3BU/I16ExZ0mY1CjpjoJxiyKe7Nbb0VEH4XO4SbjhngGPSsod+S3/HPA==", + "dev": true, "requires": { "eslint-config-prettier": "~6.11.0", "prettier-linter-helpers": "~1.0.0", @@ -2772,23 +15283,25 @@ "eslint-plugin-promise": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", - "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==" + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true }, "eslint-plugin-react": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz", - "integrity": "sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "dev": true, "requires": { "array-includes": "^3.1.1", "array.prototype.flatmap": "^1.2.3", "doctrine": "^2.1.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", "object.entries": "^1.1.2", "object.fromentries": "^2.0.2", "object.values": "^1.1.1", "prop-types": "^15.7.2", - "resolve": "^1.17.0", + "resolve": "^1.18.1", "string.prototype.matchall": "^4.0.2" }, "dependencies": { @@ -2796,57 +15309,172 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "requires": { "esutils": "^2.0.2" } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } } } }, "eslint-plugin-react-hooks": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.8.tgz", - "integrity": "sha512-6SSb5AiMCPd8FDJrzah+Z4F44P2CdOaK026cXFV+o/xSRzfOiV1FNFeLl2z6xm3yqWOQEZ5OfVgiec90qV2xrQ==" - }, - "eslint-plugin-standard": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.2.tgz", - "integrity": "sha512-nKptN8l7jksXkwFk++PhJB3cCDTcXOEyhISIN86Ue2feJ1LFyY3PrY3/xT2keXlJSY5bpmbiTG0f885/YKAvTA==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", + "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", + "dev": true, + "requires": {} }, "eslint-plugin-unicorn": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-21.0.0.tgz", - "integrity": "sha512-S8v7+v4gZTQPj4pKKvexhgSUaLQSyItvxW2SVZDaX9Iu5IjlAmF2eni+L6w8a2aqshxgU8Lle4FIAVDtuejSKQ==", + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-26.0.1.tgz", + "integrity": "sha512-SWgF9sIVY74zqkkSN2dclSCqRfocWSUGD0haC0NX2oRfmdp9p8dQvJYkYSQePaCyssPUE/pqpsIEEZNTh8crUA==", + "dev": true, "requires": { "ci-info": "^2.0.0", "clean-regexp": "^1.0.0", "eslint-ast-utils": "^1.1.0", - "eslint-template-visitor": "^2.0.0", + "eslint-template-visitor": "^2.2.2", "eslint-utils": "^2.1.0", - "import-modules": "^2.0.0", - "lodash": "^4.17.15", + "import-modules": "^2.1.0", + "lodash": "^4.17.20", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.21", "reserved-words": "^0.1.2", "safe-regex": "^2.1.1", - "semver": "^7.3.2" + "semver": "^7.3.4" }, "dependencies": { - "safe-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", - "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, "requires": { - "regexp-tree": "~0.1.1" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, @@ -2854,46 +15482,45 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "eslint-template-visitor": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.2.2.tgz", - "integrity": "sha512-SkcLjzKw3JjKTWHacRDeLBa2gxb600zbCKTkXj/V97QnZ9yxkknoPL8vc8PFueqbFXP7mYNTQzjCjcMpTRdRaA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz", + "integrity": "sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==", + "dev": true, "requires": { - "babel-eslint": "^10.1.0", + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", "eslint-visitor-keys": "^2.0.0", "esquery": "^1.3.1", "multimap": "^1.1.0" } }, "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" - } + "eslint-visitor-keys": "^2.0.0" } }, "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true }, "espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, "requires": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -2903,7 +15530,8 @@ "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true } } }, @@ -2913,9 +15541,10 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, "requires": { "estraverse": "^5.1.0" }, @@ -2923,7 +15552,8 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true } } }, @@ -2931,6 +15561,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "requires": { "estraverse": "^5.2.0" }, @@ -2938,19 +15569,22 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true } } }, "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "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==" + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, "exit-on-epipe": { "version": "1.0.1", @@ -2958,22 +15592,24 @@ "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" }, "expect": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", - "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.6.tgz", + "integrity": "sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==", + "dev": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-styles": "^5.0.0", - "jest-get-type": "^27.0.1", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-regex-util": "^27.0.1" + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.0.6", + "jest-message-util": "^27.0.6", + "jest-regex-util": "^27.0.6" }, "dependencies": { "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, @@ -2995,19 +15631,20 @@ "fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true }, "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" } }, "fast-json-stable-stringify": { @@ -3018,12 +15655,14 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fastq": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", - "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", + "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", + "dev": true, "requires": { "reusify": "^1.0.4" } @@ -3034,9 +15673,10 @@ "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==" }, "file-entry-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", - "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "requires": { "flat-cache": "^3.0.4" } @@ -3045,6 +15685,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -3053,100 +15694,130 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, "requires": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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 + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + } } }, "find-parent-dir": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=" + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true }, "find-project-root": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/find-project-root/-/find-project-root-1.1.1.tgz", - "integrity": "sha1-0kJyei2QRyXfVxTyPf3N7doLbvg=" + "integrity": "sha1-0kJyei2QRyXfVxTyPf3N7doLbvg=", + "dev": true }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "locate-path": "^2.0.0" } }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" } }, "flatted": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", - "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", + "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==", + "dev": true }, "flatten": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", - "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==" + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true }, "foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, "requires": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } } }, "forever-agent": { @@ -3167,7 +15838,8 @@ "fromentries": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==" + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true }, "fs-constants": { "version": "1.0.0", @@ -3183,6 +15855,22 @@ "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" + }, + "dependencies": { + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + } } }, "fs-minipass": { @@ -3201,12 +15889,14 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, "gauge": { "version": "2.7.4", @@ -3221,55 +15911,25 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } } }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "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==" + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -3279,12 +15939,22 @@ "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true }, "get-stdin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==" + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } }, "getpass": { "version": "0.1.7", @@ -3297,12 +15967,27 @@ "git-config-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-2.0.0.tgz", - "integrity": "sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==" + "integrity": "sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==", + "dev": true + }, + "git-documentdb-plugin-remote-nodegit": { + "version": "https://registry.npmjs.org/git-documentdb-plugin-remote-nodegit/-/git-documentdb-plugin-remote-nodegit-1.0.3.tgz", + "integrity": "sha512-80cxPE+jIjDpECCXAmNtjZxMFVNc38yFkZmEd3hRp6EvSQhX6nky0kmEFWZ1aeFnTq0oATEJvEJg9yO8zYkyng==", + "requires": { + "git-documentdb-remote-errors": "^1.0.3", + "nodegit": "^0.27.0", + "tslog": "^3.2.0" + } + }, + "git-documentdb-remote-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-documentdb-remote-errors/-/git-documentdb-remote-errors-1.0.3.tgz", + "integrity": "sha512-14fN8VAQeBC7+Phs6TYB1D5PJDE/dF8dxbigKpsBEqR1FvpAQerSPptxVsQgkU33xwwZBOm7yCwVD2KKmQatOQ==" }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3313,22 +15998,36 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { "is-glob": "^4.0.1" } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", + "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } }, "globby": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -3342,6 +16041,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/glub/-/glub-1.0.3.tgz", "integrity": "sha1-VsFkMpiuJQZcYxUAMze7pp0vuGY=", + "dev": true, "requires": { "glob": "^5.0.5", "minimist": "^1.1.1" @@ -3351,6 +16051,7 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, "requires": { "inflight": "^1.0.4", "inherits": "2", @@ -3373,50 +16074,38 @@ "cacheable-request": "^7.0.1", "decompress-response": "^5.0.0", "duplexer3": "^0.1.4", - "get-stream": "^5.0.0", - "lowercase-keys": "^2.0.0", - "mimic-response": "^2.1.0", - "p-cancelable": "^2.0.0", - "p-event": "^4.0.0", - "responselike": "^2.0.0", - "to-readable-stream": "^2.0.0", - "type-fest": "^0.10.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "type-fest": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", - "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==" - } + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "graphql": { "version": "15.3.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz", - "integrity": "sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==" + "integrity": "sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==", + "dev": true }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, "requires": { "minimist": "^1.2.5", "neo-async": "^2.6.0", @@ -3443,19 +16132,27 @@ "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-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "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==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true }, "has-unicode": { "version": "2.0.1", @@ -3466,47 +16163,55 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, "requires": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" }, "dependencies": { - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true }, "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==" + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true }, "html-element-attributes": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/html-element-attributes/-/html-element-attributes-2.2.1.tgz", - "integrity": "sha512-gGTgCeQu+g1OFExZKWQ1LwbFXxLJ6cGdCGj64ByEaxatr/EPVc23D6Gxngb37ao+SNInP/sGu8FXxRsSxMm7aQ==" + "integrity": "sha512-gGTgCeQu+g1OFExZKWQ1LwbFXxLJ6cGdCGj64ByEaxatr/EPVc23D6Gxngb37ao+SNInP/sGu8FXxRsSxMm7aQ==", + "dev": true }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, "html-styles": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/html-styles/-/html-styles-1.0.0.tgz", - "integrity": "sha1-oYBh/WUfmca3XEXI4FSaO8PgGnU=" + "integrity": "sha1-oYBh/WUfmca3XEXI4FSaO8PgGnU=", + "dev": true }, "html-tag-names": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/html-tag-names/-/html-tag-names-1.1.5.tgz", - "integrity": "sha512-aI5tKwNTBzOZApHIynaAwecLBv8TlZTEy/P4Sj2SzzAhBrGuI8yGZ0UIXVPQzOHGS+to2mjb04iy6VWt/8+d8A==" + "integrity": "sha512-aI5tKwNTBzOZApHIynaAwecLBv8TlZTEy/P4Sj2SzzAhBrGuI8yGZ0UIXVPQzOHGS+to2mjb04iy6VWt/8+d8A==", + "dev": true }, "http-cache-semantics": { "version": "4.1.0", @@ -3537,9 +16242,9 @@ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", "requires": { "minimatch": "^3.0.4" } @@ -3548,42 +16253,41 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - } } }, "import-lazy": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==" + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true }, "import-modules": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", - "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==" + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true }, "indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true }, "inflight": { "version": "1.0.6", @@ -3605,44 +16309,27 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, "requires": { - "es-abstract": "^1.17.0-next.1", + "get-intrinsic": "^1.1.0", "has": "^1.0.3", - "side-channel": "^1.0.2" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "side-channel": "^1.0.4" } }, "is-alphabetical": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true }, "is-alphanumerical": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -3651,53 +16338,85 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "requires": { "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, "requires": { "has": "^1.0.3" } }, "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==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true }, "is-decimal": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -3705,42 +16424,67 @@ "is-hexadecimal": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true }, "is-negative-zero": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, "requires": { - "has-symbols": "^1.0.1" + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" } }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "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==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-typedarray": { @@ -3751,17 +16495,20 @@ "is-whitespace-character": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "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==" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true }, "is-word-character": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true }, "isarray": { "version": "1.0.0", @@ -3774,9 +16521,8 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isomorphic-git": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.8.2.tgz", - "integrity": "sha512-wp3on2Kks1sE/tLUmGLPV7EEAj+JRK8WoL2ZSfJHVQfWzRqMRv96bqzDjyYpC6COGKlDQnhTNCucRf83S3cuMw==", + "version": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.9.1.tgz", + "integrity": "sha512-vzceJaiBdaJI5aT1di4dxWWf6sao3WQFQJ6UTi1tXO4zyDfsuyIadVOA4YQzdwKhLilV9msgM8HIvpOE94kmQg==", "requires": { "async-lock": "^1.1.0", "clean-git-ref": "^2.0.1", @@ -3791,11 +16537,6 @@ "simple-get": "^3.0.2" }, "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -3816,12 +16557,14 @@ "istanbul-lib-coverage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==" + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true }, "istanbul-lib-hook": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, "requires": { "append-transform": "^2.0.0" } @@ -3830,6 +16573,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, "requires": { "@babel/core": "^7.7.5", "@istanbuljs/schema": "^0.1.2", @@ -3840,7 +16584,8 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -3848,6 +16593,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, "requires": { "archy": "^1.0.0", "cross-spawn": "^7.0.0", @@ -3856,235 +16602,305 @@ "p-map": "^3.0.0", "rimraf": "^3.0.0", "uuid": "^3.3.3" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - } } }, "istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, "requires": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "istanbul-lib-source-maps": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, "requires": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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": "3.0.2", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "jest-diff": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", - "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", + "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", + "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.1", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-docblock": { "version": "26.0.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-get-type": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", - "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==" + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", + "dev": true }, "jest-matcher-utils": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", - "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz", + "integrity": "sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==", + "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "jest-diff": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.0.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", + "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", + "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.0.6", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", - "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==" - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } + "color-convert": "^2.0.1" } }, - "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==", + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, "requires": { - "color-convert": "^1.9.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } }, "jest-regex-util": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", - "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==" + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", + "dev": true }, "jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "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==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -4098,7 +16914,8 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true }, "json-buffer": { "version": "3.0.1", @@ -4108,7 +16925,8 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "json-schema": { "version": "0.2.3", @@ -4124,6 +16942,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, "requires": { "jsonify": "~0.0.0" } @@ -4131,7 +16950,8 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -4139,26 +16959,26 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "requires": { "minimist": "^1.2.5" } }, "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.6" } }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true }, "jsprim": { "version": "1.4.1", @@ -4172,18 +16992,20 @@ } }, "jsx-ast-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", - "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", + "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "dev": true, "requires": { - "array-includes": "^3.1.1", - "object.assign": "^4.1.0" + "array-includes": "^3.1.2", + "object.assign": "^4.1.2" } }, "just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true }, "keyv": { "version": "4.0.3", @@ -4196,27 +17018,42 @@ "lcov-parse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=" + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "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==" + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true }, "linguist-languages": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-7.10.0.tgz", - "integrity": "sha512-Uqt94P4iAznscZtccnNE1IBi105U+fmQKEUlDJv54JDdFZDInomkepEIRpZLOQcPyGdcNu3JO9Tvo5wpQVbfKw==" + "integrity": "sha512-Uqt94P4iAznscZtccnNE1IBi105U+fmQKEUlDJv54JDdFZDInomkepEIRpZLOQcPyGdcNu3JO9Tvo5wpQVbfKw==", + "dev": true }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -4224,71 +17061,142 @@ "strip-bom": "^3.0.0" }, "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true }, "lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true }, "lodash.zip": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", - "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=" + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "dev": true }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, "requires": { "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "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" } @@ -4304,12 +17212,20 @@ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "requires": { "semver": "^6.0.0" }, @@ -4317,19 +17233,22 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "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==" + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, "requires": { "p-defer": "^1.0.0" } @@ -4337,51 +17256,54 @@ "markdown-escapes": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", - "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true }, "mem": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.1.tgz", "integrity": "sha512-Ci6bIfq/UgcxPTYa8dQQ5FY3BzKkT894bwXWXxC/zqs0XgMO2cT20CGkOqda7gZNkmK5VP4x89IGZ6K7hfbn3Q==", + "dev": true, "requires": { "map-age-cleaner": "^0.1.3", "mimic-fn": "^3.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", - "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==" - } } }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" } }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" }, "mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "requires": { - "mime-db": "1.45.0" + "mime-db": "1.48.0" } }, + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true + }, "mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", @@ -4415,13 +17337,6 @@ "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" - }, - "dependencies": { - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - } } }, "minizlib": { @@ -4432,10 +17347,19 @@ "minipass": "^2.9.0" } }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, "mocha": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", - "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", @@ -4467,41 +17391,73 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "ms": "2.1.2" + }, + "dependencies": { + "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 + } } }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==" + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.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" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "js-yaml": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, "requires": { "argparse": "^2.0.1" } @@ -4510,19 +17466,16 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "requires": { "p-locate": "^5.0.0" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "requires": { "yocto-queue": "^0.1.0" } @@ -4531,14 +17484,28 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "requires": { "p-limit": "^3.0.2" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -4547,60 +17514,29 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==" - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==" } } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "multimap": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", - "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==" + "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==", + "dev": true }, "n-readlines": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/n-readlines/-/n-readlines-1.0.1.tgz", - "integrity": "sha512-z4SyAIVgMy7CkgsoNw7YVz40v0g4+WWvvqy8+ZdHrCtgevcEO758WQyrYcw3XPxcLxF+//RszTz/rO48nzD0wQ==" + "integrity": "sha512-z4SyAIVgMy7CkgsoNw7YVz40v0g4+WWvvqy8+ZdHrCtgevcEO758WQyrYcw3XPxcLxF+//RszTz/rO48nzD0wQ==", + "dev": true }, "nan": { "version": "2.14.2", @@ -4610,42 +17546,36 @@ "nanoid": { "version": "3.1.20", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true }, "needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz", + "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } } }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true }, "nise": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", "@sinonjs/fake-timers": "^6.0.0", @@ -4677,14 +17607,6 @@ "which": "1" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -4694,9 +17616,11 @@ } }, "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + "version": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } } } }, @@ -4717,6 +17641,36 @@ "tar": "^4" }, "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -4741,6 +17695,25 @@ "requires": { "glob": "^7.1.3" } + }, + "tar": { + "version": "4.4.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.15.tgz", + "integrity": "sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==", + "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" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" } } }, @@ -4748,10 +17721,45 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, "requires": { "process-on-spawn": "^1.0.0" } }, + "node-releases": { + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "dev": true + }, + "nodegit": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/nodegit/-/nodegit-0.27.0.tgz", + "integrity": "sha512-E9K4gPjWiA0b3Tx5lfWCzG7Cvodi2idl3V5UD2fZrOrHikIfrN7Fc2kWLtMUqqomyoToYJLeIC8IV7xb1CYRLA==", + "requires": { + "fs-extra": "^7.0.0", + "got": "^10.7.0", + "json5": "^2.1.0", + "lodash": "^4.17.14", + "nan": "^2.14.0", + "node-gyp": "^4.0.0", + "node-pre-gyp": "^0.13.0", + "ramda": "^0.25.0", + "tar-fs": "^1.16.3" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -4764,6 +17772,7 @@ "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", @@ -4774,17 +17783,18 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", "requires": { "npm-normalize-package-bin": "^1.0.1" } @@ -4824,6 +17834,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, "requires": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -4852,6 +17863,188 @@ "spawn-wrap": "^2.0.0", "test-exclude": "^6.0.0", "yargs": "^15.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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 + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, "oauth-sign": { @@ -4865,19 +18058,22 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==" + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "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==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", @@ -4886,36 +18082,37 @@ } }, "object.entries": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", - "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.4.tgz", + "integrity": "sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==", + "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" + "es-abstract": "^1.18.2" } }, "object.fromentries": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", - "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", + "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", + "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, "object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", + "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" + "es-abstract": "^1.18.2" } }, "once": { @@ -4926,6 +18123,20 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -4969,14 +18180,15 @@ } }, "p-cancelable": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", - "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true }, "p-event": { "version": "4.2.0", @@ -4992,25 +18204,28 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "requires": { - "p-try": "^2.0.0" + "p-try": "^1.0.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^1.1.0" } }, "p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, "requires": { "aggregate-error": "^3.0.0" } @@ -5024,14 +18239,16 @@ } }, "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==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, "package-hash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, "requires": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", @@ -5048,6 +18265,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { "callsites": "^3.0.0" } @@ -5056,6 +18274,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, "requires": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -5069,41 +18288,49 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-3.0.0.tgz", "integrity": "sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA==", + "dev": true, "requires": { "git-config-path": "^2.0.0", "ini": "^1.3.5" } }, "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "error-ex": "^1.2.0" } }, "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "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=" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "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==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, "requires": { "isarray": "0.0.1" }, @@ -5111,14 +18338,16 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true } } }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true }, "performance-now": { "version": "2.1.0", @@ -5126,27 +18355,30 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^2.1.0" } }, "please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, "requires": { "semver-compare": "^1.0.0" } @@ -5154,68 +18386,25 @@ "pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true }, "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "dev": true, "requires": { "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.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==", - "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=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, + "source-map": "^0.6.1", + "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" } @@ -5226,6 +18415,7 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz", "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==", + "dev": true, "requires": { "postcss": "^7.0.14" } @@ -5233,12 +18423,14 @@ "postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=" + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true }, "postcss-scss": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz", "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==", + "dev": true, "requires": { "postcss": "^7.0.6" } @@ -5247,6 +18439,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, "requires": { "flatten": "^1.0.2", "indexes-of": "^1.0.1", @@ -5257,16 +18450,24 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dev": true, "requires": { "flatten": "^1.0.2", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, "requires": { "fast-diff": "^1.1.2" } @@ -5275,6 +18476,7 @@ "version": "0.14.3", "resolved": "https://registry.npmjs.org/prettierx/-/prettierx-0.14.3.tgz", "integrity": "sha512-0VT3GgDAU6rvemeklrRzqVkILrGC1TSo/4STnsBqkreLx5Ck43W05lO60pMKWbG7SWM3DcUZZIR4FZ5pvvDwyQ==", + "dev": true, "requires": { "@angular/compiler": "9.0.5", "@babel/code-frame": "7.12.11", @@ -5336,15 +18538,26 @@ "yaml-unist-parser": "1.3.1" }, "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, "@babel/parser": { "version": "7.12.0", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.0.tgz", - "integrity": "sha512-dYmySMYnlus2jwl7JnnajAj11obRStZoW9cG04wh4ZuhozDn11tDUrhHcUZ9iuNHqALAhh60XqNaYXpvuuE/Gg==" + "integrity": "sha512-dYmySMYnlus2jwl7JnnajAj11obRStZoW9cG04wh4ZuhozDn11tDUrhHcUZ9iuNHqALAhh60XqNaYXpvuuE/Gg==", + "dev": true }, "@typescript-eslint/typescript-estree": { "version": "2.34.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", + "dev": true, "requires": { "debug": "^4.1.1", "eslint-visitor-keys": "^1.1.0", @@ -5355,30 +18568,92 @@ "tsutils": "^3.17.1" } }, - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } }, "get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", - "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==" + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true }, "globby": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -5391,40 +18666,114 @@ "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true } } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "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 + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", + "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", + "dev": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.0.6", "ansi-regex": "^5.0.0", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" }, "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true } } }, @@ -5442,6 +18791,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, "requires": { "fromentries": "^1.2.0" } @@ -5449,12 +18799,14 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "prop-types": { "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -5464,14 +18816,16 @@ "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true } } }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "psl": { "version": "1.8.0", @@ -5497,6 +18851,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "ramda": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", @@ -5506,6 +18866,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -5519,46 +18880,50 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - } } }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" }, "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" } }, "readable-stream": { @@ -5579,61 +18944,47 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, "requires": { "picomatch": "^2.2.1" } }, "regexp-tree": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.21.tgz", - "integrity": "sha512-kUUXjX4AnqnR8KRTCrayAo9PzYMRKmVoGgaz2tBuz0MF3g1ZbGebmtW0yFHfFK9CmBjQKeYIgoL22pFLBJY7sw==" + "version": "0.1.23", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.23.tgz", + "integrity": "sha512-+7HWfb4Bvu8Rs2eQTUIpX9I/PlQkYOuTNbRpKLJlQpSgwSkzFYh+pUj0gtvglnOZLKB6YgnIgRuJ2/IlpL48qw==", + "dev": true }, "regexp-util": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/regexp-util/-/regexp-util-1.2.2.tgz", "integrity": "sha512-5/rl2UD18oAlLQEIuKBeiSIOp1hb5wCXcakl5yvHxlY1wyWI4D5cUKKzCibBeu741PA9JKvZhMqbkDQqPusX3w==", + "dev": true, "requires": { "tslib": "^1.9.0" } }, "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, "requires": { "es6-error": "^4.0.1" } @@ -5642,6 +18993,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-1.0.6.tgz", "integrity": "sha512-I43wU/QOQpXvVFXKjA4FHp5xptK65+5F6yolm8+69/JV0EqSOB64wURUZ3JK50JtnTL8FvwLiH2PZ+fvsBxviA==", + "dev": true, "requires": { "trim-trailing-lines": "^1.1.0" } @@ -5650,6 +19002,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, "requires": { "collapse-white-space": "^1.0.2", "is-alphabetical": "^1.0.0", @@ -5671,7 +19024,8 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "request": { "version": "2.88.2", @@ -5698,57 +19052,46 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "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==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } } }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "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==" + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "reserved-words": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", - "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=" + "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", + "dev": true }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "requires": { - "is-core-module": "^2.1.0", "path-parse": "^1.0.6" } }, "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true }, "responselike": { "version": "2.0.0", @@ -5761,7 +19104,8 @@ "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true }, "rimraf": { "version": "3.0.2", @@ -5772,15 +19116,28 @@ } }, "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "requires": { + "regexp-tree": "~0.1.1" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5792,19 +19149,21 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "semver-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true }, "serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, "requires": { "randombytes": "^2.1.0" } @@ -5823,10 +19182,26 @@ "safe-buffer": "^5.0.1" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -5836,7 +19211,8 @@ "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true }, "signal-exit": { "version": "3.0.3", @@ -5869,14 +19245,16 @@ } }, "simple-html-tokenizer": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.10.tgz", - "integrity": "sha512-1DHMUmvUOGuUZ9/+cX/+hOhWhRD5dEw6lodn8WuV+T+cQ31hhBcCu1dcDsNotowi4mMaNhrLyKoS+DtB81HdDA==" + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz", + "integrity": "sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og==", + "dev": true }, "sinon": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", @@ -5884,21 +19262,72 @@ "diff": "^4.0.2", "nise": "^4.1.0", "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, "slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "requires": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + } } }, "source-map": { @@ -5919,6 +19348,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, "requires": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", @@ -5932,6 +19362,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -5942,6 +19373,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -5950,21 +19382,24 @@ "spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true }, "spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==" + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "dev": true }, "sprintf-js": { "version": "1.0.3", @@ -5974,7 +19409,8 @@ "srcset": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/srcset/-/srcset-3.0.0.tgz", - "integrity": "sha512-D59vF08Qzu/C4GAOXVgMTLfgryt5fyWo93FZyhEWANo0PokFz/iWdDe13mX3O5TRf6l8vMTqckAfR4zPiaH0yQ==" + "integrity": "sha512-D59vF08Qzu/C4GAOXVgMTLfgryt5fyWo93FZyhEWANo0PokFz/iWdDe13mX3O5TRf6l8vMTqckAfR4zPiaH0yQ==", + "dev": true }, "sshpk": { "version": "1.16.1", @@ -5996,6 +19432,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "dev": true, "requires": { "escape-string-regexp": "^2.0.0" }, @@ -6003,111 +19440,123 @@ "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true } } }, "state-toggle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } }, "string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==" + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string.prototype.matchall": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", - "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz", + "integrity": "sha512-Z5ZaXO0svs0M2xd/6By3qpeKpLKd9mO4v4q3oMEQrk8Ck4xOD5d5XeBOOjGrmVZZ/AHB1S0CgG4N5r1G9N3E2Q==", + "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3" + "es-abstract": "^1.18.2", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^2.0.0" } }, "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" } }, "table": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", - "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", - "requires": { - "ajv": "^7.0.2", - "lodash": "^4.17.20", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz", + "integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -6115,17 +19564,50 @@ "uri-js": "^4.2.2" } }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } } } }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "4.4.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.15.tgz", + "integrity": "sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==", "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", @@ -6134,21 +19616,6 @@ "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.3" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - } } }, "tar-fs": { @@ -6162,6 +19629,11 @@ "tar-stream": "^1.1.2" }, "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -6199,6 +19671,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, "requires": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -6208,12 +19681,14 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true }, "timsort": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true }, "to-buffer": { "version": "1.1.1", @@ -6223,7 +19698,8 @@ "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=" + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true }, "to-readable-stream": { "version": "2.1.0", @@ -6234,14 +19710,25 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "requires": { "is-number": "^7.0.0" } }, + "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==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, "transform-file": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/transform-file/-/transform-file-1.0.1.tgz", "integrity": "sha1-f5WYSs0j1Ov4q7R+6dg74WbRJoc=", + "dev": true, "requires": { "os-tmpdir": "^1.0.0" } @@ -6249,23 +19736,31 @@ "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true }, "trim-trailing-lines": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", - "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==" + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "dev": true }, "trough": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "requires": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", + "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", + "dev": true, + "requires": { + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", @@ -6275,48 +19770,35 @@ } }, "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz", + "integrity": "sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==", + "dev": true, "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^2.2.0", "minimist": "^1.2.0", "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - } } }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "tslog": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.1.2.tgz", - "integrity": "sha512-sKhNPUMjf+POPxcWuGxinjilEjIzPCdehF/zIdp33ttv9ohIBWHMV9gpdGvJjWbZn09a5IqP1dmaYq56IPXZAg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.2.0.tgz", + "integrity": "sha512-xOCghepl5w+wcI4qXI7vJy6c53loF8OoC/EuKz1ktAPMtltEDz00yo1poKuyBYIQaq4ZDYKYFPD9PfqVrFXh0A==", "requires": { "source-map-support": "^0.5.19" } }, "tsutils": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.0.tgz", - "integrity": "sha512-A7BaLUPvcQ1cxVu72YfD+UMI3SQPTDv/w4ol6TOwLyI0hwfG9EC+cYlhdflJTmtYTgZ3KqdPSe/otxU4K3kArg==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, "requires": { "tslib": "^1.8.1" } @@ -6334,33 +19816,46 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==" }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, "requires": { "is-typedarray": "^1.0.0" } }, "typescript": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", - "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==" + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true }, "uglify-js": { - "version": "3.12.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.4.tgz", - "integrity": "sha512-L5i5jg/SHkEqzN18gQMTWsZk3KelRsfD1wUVNqtq0kzqWQqcJjyL8yc1o8hJgRrWqrAl2mUFbhfznEIoi7zi2A==", + "version": "3.13.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.10.tgz", + "integrity": "sha512-57H3ACYFXeo1IaZ1w02sfA71wI60MGco/IQFjOqK+WtKoprh7Go2/yvd2HPtoJILO2Or84ncLccI4xoHMTSbGg==", + "dev": true, "optional": true }, "ulid": { @@ -6368,10 +19863,23 @@ "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==" }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "unherit": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, "requires": { "inherits": "^2.0.0", "xtend": "^4.0.0" @@ -6381,6 +19889,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-3.0.0.tgz", "integrity": "sha512-WiDJdORsqgxkZrjC8WsIP573130HNn7KsB0IDnUccW2BG2b19QQNloNhVe6DKk3Aef0UcoIHhNVj7IkkcYWrNw==", + "dev": true, "requires": { "regexp-util": "^1.2.0" } @@ -6394,6 +19903,7 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dev": true, "requires": { "bail": "^1.0.0", "extend": "^3.0.0", @@ -6401,29 +19911,25 @@ "is-plain-obj": "^2.0.0", "trough": "^1.0.0", "vfile": "^4.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - } } }, "uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true }, "unist-util-is": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", - "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true }, "unist-util-remove-position": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "dev": true, "requires": { "unist-util-visit": "^1.1.0" } @@ -6432,6 +19938,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, "requires": { "@types/unist": "^2.0.2" } @@ -6440,6 +19947,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, "requires": { "unist-util-visit-parents": "^2.0.0" } @@ -6448,6 +19956,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, "requires": { "unist-util-is": "^3.0.0" } @@ -6458,14 +19967,14 @@ "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" }, "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } @@ -6475,15 +19984,22 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "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" @@ -6492,7 +20008,8 @@ "validator": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz", - "integrity": "sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==" + "integrity": "sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==", + "dev": true }, "verror": { "version": "1.10.0", @@ -6508,29 +20025,25 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dev": true, "requires": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", "unist-util-stringify-position": "^2.0.0", "vfile-message": "^2.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - } } }, "vfile-location": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", - "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", + "dev": true }, "vfile-message": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, "requires": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^2.0.0" @@ -6540,60 +20053,18 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/vnopts/-/vnopts-1.0.2.tgz", "integrity": "sha512-d2rr2EFhAGHnTlURu49G7GWmiJV80HbAnkYdD9IFAtfhmxC+kSWEaZ6ZF064DJFTv9lQZQV1vuLTntyQpoanGQ==", + "dev": true, "requires": { "chalk": "^2.4.1", "leven": "^2.1.0", "tslib": "^1.9.3" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.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==", - "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=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, "leven": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true } } }, @@ -6605,10 +20076,24 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true }, "wide-align": { "version": "1.1.3", @@ -6616,186 +20101,1153 @@ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" + } + }, + "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 + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yaml-unist-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/yaml-unist-parser/-/yaml-unist-parser-1.3.1.tgz", + "integrity": "sha512-4aHBMpYcnByF8l2OKj5hlBJlxSYIMON8Z1Hm57ymbBL4omXMlGgY+pEf4Di6h2qNT8ZG8seTVvAQYNOa7CZ9eA==", + "dev": true, + "requires": { + "lines-and-columns": "^1.1.6", + "tslib": "^1.10.0", + "yaml": "^1.10.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "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=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } } } }, - "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==" + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } }, - "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==" + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + }, + "z-schema": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.18.4.tgz", + "integrity": "sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw==", + "dev": true, + "requires": { + "commander": "^2.7.1", + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^8.0.0" + } + } + } + }, + "git-documentdb-plugin-remote-nodegit": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/git-documentdb-plugin-remote-nodegit/-/git-documentdb-plugin-remote-nodegit-1.0.4.tgz", + "integrity": "sha512-+esXlN6PMmvwKZPU6dn/kSQnVe5QHU9xGzoNrLiqehz+VM1AXgNhsce/KipimG4wdzUS6tbS9QbgIgA4VjpbAw==", + "requires": { + "@sosuisen/nodegit": "^0.28.0-alpha.11", + "git-documentdb-remote-errors": "^1.0.3", + "tslog": "^3.2.0" + } + }, + "git-documentdb-remote-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-documentdb-remote-errors/-/git-documentdb-remote-errors-1.0.3.tgz", + "integrity": "sha512-14fN8VAQeBC7+Phs6TYB1D5PJDE/dF8dxbigKpsBEqR1FvpAQerSPptxVsQgkU33xwwZBOm7yCwVD2KKmQatOQ==" + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + }, + "got": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", + "integrity": "sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==", + "requires": { + "@sindresorhus/is": "^2.0.0", + "@szmarczak/http-timer": "^4.0.0", + "@types/cacheable-request": "^6.0.1", + "cacheable-lookup": "^2.0.0", + "cacheable-request": "^7.0.1", + "decompress-response": "^5.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "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==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "requires": { + "json-buffer": "3.0.1" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mime-db": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==" + }, + "mime-types": { + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "requires": { + "mime-db": "1.49.0" + } + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "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==" + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "needle": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz", + "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + } + }, + "node-pre-gyp": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz", + "integrity": "sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==", + "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" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "minipass": "^2.6.0" } }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yaml": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", - "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } }, - "yaml-unist-parser": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/yaml-unist-parser/-/yaml-unist-parser-1.3.1.tgz", - "integrity": "sha512-4aHBMpYcnByF8l2OKj5hlBJlxSYIMON8Z1Hm57ymbBL4omXMlGgY+pEf4Di6h2qNT8ZG8seTVvAQYNOa7CZ9eA==", + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "requires": { - "lines-and-columns": "^1.1.6", - "tslib": "^1.10.0", - "yaml": "^1.10.0" + "minimist": "^1.2.5" } }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.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": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "abbrev": "1", + "osenv": "^0.1.4" } }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "glob": "^7.1.3" } }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "tar": { + "version": "4.4.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.15.tgz", + "integrity": "sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==", "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" - } + "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" } }, - "yn": { + "yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, + "npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "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", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" + }, + "p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "requires": { + "p-timeout": "^3.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "requires": { + "p-finally": "^1.0.0" + } + }, + "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=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "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==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "ramda": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", + "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "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" + } + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "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==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz", + "integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } }, - "z-schema": { - "version": "3.18.4", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.18.4.tgz", - "integrity": "sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw==", + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", "requires": { - "commander": "^2.7.1", - "lodash.get": "^4.0.0", - "lodash.isequal": "^4.0.0", - "validator": "^8.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } } } }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "to-readable-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==" + }, + "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==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tslog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.2.0.tgz", + "integrity": "sha512-xOCghepl5w+wcI4qXI7vJy6c53loF8OoC/EuKz1ktAPMtltEDz00yo1poKuyBYIQaq4ZDYKYFPD9PfqVrFXh0A==", + "requires": { + "source-map-support": "^0.5.19" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-fest": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==" + }, "typescript": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/examples/package.json b/examples/package.json index 022c135e..711830d8 100644 --- a/examples/package.json +++ b/examples/package.json @@ -7,12 +7,15 @@ "build": "rm -rf dist/ && tsc", "start": "npm run build && node dist/index.js", "collection": "npm run build && node dist/collection.js", - "sync": "rm -rf ./git-documentdb/ && npm run build && node dist/sync.js" + "sync": "rm -rf ./git-documentdb/ && npm run build && node dist/sync.js", + "plugin": "npm run build && node dist/plugin.js", + "clear": "npx rimraf node_modules" }, "author": "", "license": "MPL-2.0", "dependencies": { - "git-documentdb": "file:.." + "git-documentdb": "file:..", + "git-documentdb-plugin-remote-nodegit": "^1.0.4" }, "devDependencies": { "typescript": "^4.1.3" diff --git a/examples/src/collection.ts b/examples/src/collection.ts index 1b132f67..e3d94f0a 100644 --- a/examples/src/collection.ts +++ b/examples/src/collection.ts @@ -88,16 +88,7 @@ const collection_example = async () => { console.log(`\n_id of the JSON document is automatically generated with a specified prefix.`); console.log(pencil); // log: { name: 'pencil', _id: 'item_XXXXXXXXXXXXXXXXXXXXXXXXXX' } - - // Add a prefix to a new root collection whose collectionPath is ''. - const myCollection = new Collection(gitDDB, '', undefined, { namePrefix: 'fruit_' }); - // '/your/path/to/the/example/git-documentdb/db_collection/item_XXXXXXXXXXXXXXXXXXXXXXXXXX.json' is created. - const durianResult = await myCollection.put({ name: 'durian' }); - const durian = await gitDDB.get(durianResult._id); - console.log(`\nJSON document is created under the working directory with a specified prefix`); - console.log(durian); - // log: { name: 'durian', _id: 'fruit_XXXXXXXXXXXXXXXXXXXXXXXXXX' } - + await gitDDB.close(); }; collection_example(); diff --git a/examples/src/index.ts b/examples/src/index.ts index 80020638..5ea33520 100644 --- a/examples/src/index.ts +++ b/examples/src/index.ts @@ -9,7 +9,7 @@ import { DEFAULT_SYNC_INTERVAL, GitDocumentDB, Err, Sync, Collection } from 'git-documentdb'; const gitddb_example = async () => { - let gitDDB = new GitDocumentDB({ + const gitDDB = new GitDocumentDB({ dbName: 'db01', // Git working directory }); @@ -30,7 +30,7 @@ const gitddb_example = async () => { console.log(`$ gitDDB.put({ flower: 'cherry blossoms' ... }) # Create`); console.log(await gitDDB.get('nara')); - // log: { _id: 'nara', flower: 'cherry blossoms', season: 'spring' } + // log: { flower: 'cherry blossoms', season: 'spring', _id: 'nara' } // Note that _id and a filename are linked. // So _id is better to be ASCII characters and a case-insensitive name for cross-platform. @@ -65,12 +65,26 @@ const gitddb_example = async () => { /** * Use an auto-generated _id */ - const appleResult = await gitDDB.put({ name: 'apple' }); // _id does not exist. - const apple = await gitDDB.get(appleResult._id); - console.log(`\n_id of the JSON document is automatically generated`); - console.log(apple); - // log: { name: 'apple', _id: 'XXXXXXXXXXXXXXXXXXXXXXXXXX' } - + const appleResult = await gitDDB.put({ name: 'apple' }); // _id does not exist. + const apple = await gitDDB.get(appleResult._id); + console.log(`\n_id of the JSON document is automatically generated`); + console.log(apple); + // log: { name: 'apple', _id: 'XXXXXXXXXXXXXXXXXXXXXXXXXX' } + + /** + * Set namePrefix to add a prefix to an auto-generated _id + */ + const gitDDBPrefix = new GitDocumentDB({ + dbName: 'db_prefix', + namePrefix: 'fruit_', + }); + await gitDDBPrefix.open(); + const fruitAppleResult = await gitDDBPrefix.put({ name: 'apple' }); + const fruitApple = await gitDDBPrefix.get(fruitAppleResult._id); + console.log(fruitApple); + // log: { name: 'apple', _id: 'fruit_XXXXXXXXXXXXXXXXXXXXXXXXXX' } + + /** * Revisions * @@ -84,7 +98,7 @@ const gitddb_example = async () => { console.log(`\n$ gitDDB.get('nara', 2) # Get a document two revisions older than the latest.`); console.log(oldDoc); - // log: { _id: 'nara', flower: 'cherry blossoms', season: 'spring' } + // log: { flower: 'cherry blossoms', season: 'spring', _id: 'nara' } /** * Synchronization @@ -102,7 +116,7 @@ const gitddb_example = async () => { * - GITDDB_PERSONAL_ACCESS_TOKEN * A personal access token of your GitHub account */ - if (process.env.GITDDB_GITHUB_USER_URL) github_repository = process.env.GITDDB_GITHUB_USER_URL + 'git-documentdb-example.git'; + if (process.env.GITDDB_GITHUB_USER_URL) github_repository = process.env.GITDDB_GITHUB_USER_URL + 'git-documentdb-example.git'; if (process.env.GITDDB_PERSONAL_ACCESS_TOKEN) your_github_personal_access_token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN; let sync: Sync | undefined; @@ -164,13 +178,14 @@ const gitddb_example = async () => { ] */ - if (sync) { + if (sync !== undefined) { console.log('\n# Sync immediately..'); - await sync.trySync(); + await sync.trySync(); } console.log('\n# All the local documents are pushed to the remote repository.'); // Close database await gitDDB.close(); + await gitDDBPrefix.close(); }; gitddb_example(); diff --git a/examples/src/plugin.ts b/examples/src/plugin.ts new file mode 100644 index 00000000..758e8f68 --- /dev/null +++ b/examples/src/plugin.ts @@ -0,0 +1,103 @@ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import { GitDocumentDB, RemoteOptions } from 'git-documentdb'; +import { sleep } from './utils'; +/** + * This example assumes you have an account on GitHub. + * Please get your personal access token with checked [repo]. + * (See https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token ) + */ +let github_repository = 'https://github.com/enter_your_account_name/git-documentdb-example-sync.git'; +let github_repository2 = 'git@github.com:enter_your_account_name/git-documentdb-example-sync2.git'; + +let your_github_personal_access_token = 'Enter your personal access token with checked [repo]'; + +let your_public_key_path = '/Enter/your/private/key/path'; +let your_private_key_path = '/Enter/your/public/key/path'; +/** + * You can also set them from environment variables: + * - GITDDB_GITHUB_USER_URL + * URL of your GitHub account + * e.g.) https://github.com/foo/ + * + * - GITDDB_PERSONAL_ACCESS_TOKEN + * A personal access token of your GitHub account + * + * - GITDDB_GITHUB_USER_SSH + * SSH URL of your GitHub account + * e.g.) git@github.com:foo/ + * + * - SSH_PUBLIC_KEY_PATH + * ssk public key of your GitHub account + * + * - SSH_PRIVATE_KEY_PATH + * ssk private key of your GitHub account + */ +if (process.env.GITDDB_GITHUB_USER_URL) github_repository = process.env.GITDDB_GITHUB_USER_URL + 'git-documentdb-example-sync.git'; +if (process.env.GITDDB_GITHUB_USER_SSH) github_repository2 = process.env.GITDDB_GITHUB_USER_SSH + 'git-documentdb-example-sync2.git'; +if (process.env.GITDDB_PERSONAL_ACCESS_TOKEN) your_github_personal_access_token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN; +if (process.env.SSH_PUBLIC_KEY_PATH) your_public_key_path = process.env.SSH_PUBLIC_KEY_PATH; +if (process.env.SSH_PRIVATE_KEY_PATH) your_private_key_path = process.env.SSH_PRIVATE_KEY_PATH; + + +/** + * Load NodeGit remote engine plugin to connect remote repository + */ +GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + +const remote_plugin_example = async () => { + const gitDDB = new GitDocumentDB({ + dbName: 'db_plugin', // Git working directory + }); + await gitDDB.open(); + await gitDDB.put({ name: 'foo'}); + + // Use default remote engine (isomorphic-git) + const remoteOptionsDefault: RemoteOptions = { + live: true, + remoteUrl: github_repository, + interval: 5000, // Sync every 5,000 msec + connection: { + type: 'github', + personalAccessToken: your_github_personal_access_token, + }, + }; + // Add default synchronize to DB + const syncDefault = await gitDDB.sync(remoteOptionsDefault); + console.log('## Default RemoteEngine: ' + syncDefault.engine); + syncDefault.on('start', () => { console.log('[default] synchronizing...')}); + syncDefault.on('complete', () => { console.log('[default] completed')}); + + // Set NodeGit remote engine plugin + const remoteOptionsNodeGit: RemoteOptions = { + live: true, + remoteUrl: github_repository2, + interval: 5000, // Sync every 5,000 msec + connection: { + type: 'ssh', + publicKeyPath: your_public_key_path, + privateKeyPath: your_private_key_path, + passPhrase: '', + engine: 'nodegit' + }, + }; + console.log(remoteOptionsNodeGit); + // Add extra synchronizer to DB + const syncNodeGit= await gitDDB.sync(remoteOptionsNodeGit); + + console.log('## Plugin RemoteEngine: ' + syncNodeGit.engine); + syncNodeGit.on('start', () => { console.log('[NodeGit] synchronizing...')}); + syncNodeGit.on('complete', () => { console.log('[NodeGit] completed')}); + + await sleep(10000); + await gitDDB.close(); +}; + +remote_plugin_example(); + diff --git a/package-lock.json b/package-lock.json index d2005dce..f852c19c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,519 +1,11203 @@ { "name": "git-documentdb", - "version": "0.4.0-alpha.9", - "lockfileVersion": 1, + "version": "0.4.8-alpha.2", + "lockfileVersion": 2, "requires": true, - "dependencies": { - "@angular/compiler": { + "packages": { + "": { + "name": "git-documentdb", + "version": "0.4.8-alpha.2", + "license": "MPL-2.0", + "dependencies": { + "@octokit/rest": "^18.3.5", + "@sosuisen/jsondiffpatch": "^0.4.7", + "async-lock": "^1.3.0", + "cross-blob": "^2.0.0", + "fs-extra": "^9.1.0", + "git-documentdb-plugin-remote-nodegit": "^1.0.4", + "git-documentdb-remote-errors": "^1.0.3", + "isomorphic-git": "^1.23.0", + "js-yaml": "^4.1.0", + "ot-json1": "^1.0.2", + "rimraf": "^3.0.2", + "tslog": "^3.1.2", + "ulid": "^2.3.0", + "unicount": "^1.2.0" + }, + "devDependencies": { + "@microsoft/api-extractor": "^7.16.0", + "@octokit/types": "^6.12.2", + "@sosuisen/api-documenter": "^7.13.27", + "@types/async-lock": "^1.1.2", + "@types/fs-extra": "^9.0.12", + "@types/js-yaml": "^4.0.3", + "@types/mocha": "^8.2.2", + "@types/node": "^14.14.20", + "@types/parse-git-config": "^3.0.0", + "@types/rimraf": "^3.0.0", + "@types/sinon": "^9.0.11", + "@typescript-eslint/eslint-plugin": "^4.28.0", + "@typescript-eslint/parser": "^4.28.0", + "coveralls": "^3.1.0", + "crlf": "^1.1.1", + "cross-env": "^7.0.3", + "eslint": "^7.17.0", + "eslint-config-standardize": "^0.7.1", + "eslint-plugin-prettierx": "^0.14.0", + "eslint-plugin-unicorn": "^36.0.0", + "expect": "^27.0.2", + "hmtid": "^0.1.0", + "mocha": "^8.3.2", + "nyc": "^15.1.0", + "parse-git-config": "^3.0.0", + "sinon": "^10.0.0", + "ts-node": "^10.1.0", + "tsconfig-paths": "^3.9.0", + "typescript": "^4.3.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@angular/compiler": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.5.tgz", "integrity": "sha512-TeyhRGefTOtA9N3udMrvheafoXcz/dvTTdZLcieeZQxm1SSeaQDUQ/rUH6QTOiHVNMtjOCrZ9J5rk1A4mPYuag==", - "dev": true + "dev": true, + "peerDependencies": { + "tslib": "^1.10.0" + } }, - "@babel/code-frame": { + "node_modules/@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, - "requires": { + "dependencies": { "@babel/highlight": "^7.10.4" } }, - "@babel/core": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", - "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.10", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.10", + "node_modules/@babel/compat-data": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", + "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.15.8", + "@babel/generator": "^7.15.8", + "@babel/helper-compilation-targets": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.8", + "@babel/helpers": "^7.15.4", + "@babel/parser": "^7.15.8", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.6", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "lodash": "^4.17.19", - "semver": "^5.4.1", + "semver": "^6.3.0", "source-map": "^0.5.0" }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "dev": true, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/generator": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", - "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "requires": { - "@babel/types": "^7.12.11", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", + "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.15.6", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", + "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "dev": true, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "@babel/compat-data": "^7.15.0", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-function-name": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", - "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/types": "^7.12.11" + "bin": { + "semver": "bin/semver.js" } }, - "@babel/helper-get-function-arity": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", - "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", + "node_modules/@babel/helper-function-name": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", + "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", "dev": true, - "requires": { - "@babel/types": "^7.12.10" + "dependencies": { + "@babel/helper-get-function-arity": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", - "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "node_modules/@babel/helper-get-function-arity": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", + "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", "dev": true, - "requires": { - "@babel/types": "^7.12.7" + "dependencies": { + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-module-imports": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", - "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", + "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", "dev": true, - "requires": { - "@babel/types": "^7.12.5" + "dependencies": { + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-module-transforms": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", - "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", + "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-simple-access": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/helper-validator-identifier": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "lodash": "^4.17.19" + "dependencies": { + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-optimise-call-expression": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", - "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", + "node_modules/@babel/helper-module-imports": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", + "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", "dev": true, - "requires": { - "@babel/types": "^7.12.10" + "dependencies": { + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-replace-supers": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", - "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", + "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.7", - "@babel/helper-optimise-call-expression": "^7.12.10", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.11" + "dependencies": { + "@babel/helper-module-imports": "^7.15.4", + "@babel/helper-replace-supers": "^7.15.4", + "@babel/helper-simple-access": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/helper-validator-identifier": "^7.15.7", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-simple-access": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", - "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", + "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", "dev": true, - "requires": { - "@babel/types": "^7.12.1" + "dependencies": { + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-split-export-declaration": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", - "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", + "node_modules/@babel/helper-replace-supers": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", + "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", "dev": true, - "requires": { - "@babel/types": "^7.12.11" + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.15.4", + "@babel/helper-optimise-call-expression": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true + "node_modules/@babel/helper-simple-access": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", + "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helpers": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", - "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", + "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.5", - "@babel/types": "^7.12.5" + "dependencies": { + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", + "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "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" - } - }, - "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 - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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" - } - } + "engines": { + "node": ">=6.9.0" } }, - "@babel/parser": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", - "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", - "dev": true + "node_modules/@babel/parser": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", + "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } }, - "@babel/template": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", - "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "node_modules/@babel/template": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.12.7", - "@babel/types": "^7.12.7" + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/traverse": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", - "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", + "node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, - "requires": { - "@babel/code-frame": "^7.12.11", - "@babel/generator": "^7.12.11", - "@babel/helper-function-name": "^7.12.11", - "@babel/helper-split-export-declaration": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/types": "^7.12.12", + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", + "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.4", + "@babel/helper-function-name": "^7.15.4", + "@babel/helper-hoist-variables": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/types": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", - "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.12.11", - "lodash": "^4.17.19", + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/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, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.15.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", + "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "@eslint/eslintrc": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", - "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", "dev": true, - "requires": { + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", "espree": "^7.3.0", - "globals": "^12.1.0", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.19", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - } + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "@glimmer/env": { + "node_modules/@glimmer/env": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz", "integrity": "sha1-/S0rVakCnGs3psk16MiHGucN+gc=", "dev": true }, - "@glimmer/interfaces": { - "version": "0.56.1", - "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.56.1.tgz", - "integrity": "sha512-+0KvSd7c9QmkEeCFHaBDub1DBeTONw+x6MZUcb/MlA3FfNis2aFs7kHVkjkdzp0Ust54Wn448dgWZFW27EuVJA==", + "node_modules/@glimmer/interfaces": { + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.56.2.tgz", + "integrity": "sha512-nRgcsTuyZ90aEoCuYVHKGDs3LpAv9n/JKiJ6iecpEYtyGgcPqSI3GjrJRl6k+1s5wnldEH1kjWq+ccCiXmA99w==", "dev": true, - "requires": { + "dependencies": { "@simple-dom/interface": "^1.4.0" } }, - "@glimmer/syntax": { + "node_modules/@glimmer/syntax": { "version": "0.56.1", "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.56.1.tgz", "integrity": "sha512-4TdtIQVFo9UfIVzXnXpMuzsA4mX06oF9NER8FmIPjBosNiQsYB7P8sABSG+2rtWgsh6CkFXkwvxZ++BB+alwOw==", "dev": true, - "requires": { + "dependencies": { "@glimmer/interfaces": "^0.56.1", "@glimmer/util": "^0.56.1", "handlebars": "^4.7.4", "simple-html-tokenizer": "^0.5.9" } }, - "@glimmer/util": { - "version": "0.56.1", - "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.56.1.tgz", - "integrity": "sha512-g7R5hMtZ2BLF+AsYhSE1xoh0gOJALof4/JL6zovYvqrsKTLYGK1Qe3RKXSt8dPav8Ac0LXt+cOd6jHPGSrEs+A==", + "node_modules/@glimmer/util": { + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.56.2.tgz", + "integrity": "sha512-AljXCX5HBjJkmNt4DNYmJmVvwqKjFF4lU6e0SBftwhzK85RbETYwpb3YWrghcjSCxoodwIu1zNFiKOA+xD6txw==", "dev": true, - "requires": { + "dependencies": { "@glimmer/env": "0.1.7", - "@glimmer/interfaces": "^0.56.1", + "@glimmer/interfaces": "^0.56.2", "@simple-dom/interface": "^1.4.0" } }, - "@iarna/toml": { + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "node_modules/@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", "dev": true }, - "@istanbuljs/load-nyc-config": { + "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "requires": { + "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", - "dev": true - }, - "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", "@types/yargs": "^16.0.0", "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "@jsbits/deep-clone": { + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jsbits/deep-clone": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@jsbits/deep-clone/-/deep-clone-1.1.1.tgz", "integrity": "sha512-aKhOhRv18tlhkjapBrcyAt8U1SmyzKi2QoO4GGMlXRfQhwm7USDSo/pX8MgB8tYB3MLaevuvwufynKSDA7U3EA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.2" + } }, - "@microsoft/api-extractor": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.16.0.tgz", - "integrity": "sha512-6CIpg4Iw4DWJszZMwYhh8OQ0bsmKq6CFjeCHfciDzmV+cUJ8ysJrO4LhYKNHEMOcfUYIv0EVoYul7/zMXTv9eA==", + "node_modules/@microsoft/api-extractor": { + "version": "7.18.15", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.18.15.tgz", + "integrity": "sha512-a8gPbb0gAO+gyWzGmB6eG9ACI3++JS0Y9049xKKITizbGV5PWrLlx3a5S1kSqVP7b6MxVK3QVnJskLzf8n1SkQ==", "dev": true, - "requires": { - "@microsoft/api-extractor-model": "7.13.2", + "dependencies": { + "@microsoft/api-extractor-model": "7.13.12", "@microsoft/tsdoc": "0.13.2", "@microsoft/tsdoc-config": "~0.15.2", - "@rushstack/node-core-library": "3.38.0", - "@rushstack/rig-package": "0.2.12", - "@rushstack/ts-command-line": "4.7.10", + "@rushstack/node-core-library": "3.42.2", + "@rushstack/rig-package": "0.3.2", + "@rushstack/ts-command-line": "4.10.1", "colors": "~1.2.1", "lodash": "~4.17.15", "resolve": "~1.17.0", "semver": "~7.3.0", "source-map": "~0.6.1", - "typescript": "~4.3.2" + "typescript": "~4.4.2" }, + "bin": { + "api-extractor": "bin/api-extractor" + } + }, + "node_modules/@microsoft/api-extractor-model": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.13.12.tgz", + "integrity": "sha512-BTTGg1tgcDpW3CyW6QQ3VWFLzKyHxfyNGw68EAS/MXnNKx580HE08hLWrSjM2zHQ1J35v4PBUorsRK+FBkHl5Q==", + "dev": true, "dependencies": { - "@microsoft/api-extractor-model": { - "version": "7.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.13.2.tgz", - "integrity": "sha512-gA9Q8q5TPM2YYk7rLinAv9KqcodrmRC13BVmNzLswjtFxpz13lRh0BmrqD01/sddGpGMIuWFYlfUM4VSWxnggA==", - "dev": true, - "requires": { - "@microsoft/tsdoc": "0.13.2", - "@microsoft/tsdoc-config": "~0.15.2", - "@rushstack/node-core-library": "3.38.0" - } - }, - "@rushstack/node-core-library": { - "version": "3.38.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.38.0.tgz", - "integrity": "sha512-cmvl0yQx8sSmbuXwiRYJi8TO+jpTtrLJQ8UmFHhKvgPVJAW8cV8dnpD1Xx/BvTGrJZ2XtRAIkAhBS9okBnap4w==", - "dev": true, - "requires": { - "@types/node": "10.17.13", - "colors": "~1.2.1", - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.17.0", - "semver": "~7.3.0", - "timsort": "~0.3.0", - "z-schema": "~3.18.3" - } - }, - "@types/node": { - "version": "10.17.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz", - "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==", - "dev": true - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.42.2" + } + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", + "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", + "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.0", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz", + "integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==", + "dependencies": { + "@octokit/types": "^6.34.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz", + "integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==", + "dependencies": { + "@octokit/types": "^6.34.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz", + "integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dependencies": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.34.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", + "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "dependencies": { + "@octokit/openapi-types": "^11.2.0" + } + }, + "node_modules/@rushstack/node-core-library": { + "version": "3.42.2", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.42.2.tgz", + "integrity": "sha512-LJ52CiiWxKpzejYACqphQQ3geWZFt5gswki8+0sMl8qZ08YCHbqlS3N+sMZpuBEwLWvBYfq/d3IvtdLT3zI2UA==", + "dev": true, + "dependencies": { + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~3.18.3" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/@types/node": { + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", + "dev": true + }, + "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@rushstack/rig-package": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.3.2.tgz", + "integrity": "sha512-lJbud9zBY8+OOjkeQ+4zIVCvt2I8y1C3WcVx3g6NJgjf0pi6IYfbAWXXG+mVzevQmqanNCLyhyXSNP3E6u5OvQ==", + "dev": true, + "dependencies": { + "resolve": "~1.17.0", + "strip-json-comments": "~3.1.1" + } + }, + "node_modules/@rushstack/ts-command-line": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.10.1.tgz", + "integrity": "sha512-FhWnQCjHtxmZr5sVEgoV1VHTFaPfJXQbVwujAaZUzuFfgqX+v2P9o0AXmUi/LED4tmPJp7A1nVgPx0ClyGUbWA==", + "dev": true, + "dependencies": { + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "colors": "~1.2.1", + "string-argv": "~0.3.1" + } + }, + "node_modules/@simple-dom/interface": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@simple-dom/interface/-/interface-1.4.0.tgz", + "integrity": "sha512-l5qumKFWU0S+4ZzMaLXFU8tQZsicHEMEyAxI5kDFGhJsRqDwe0a7/iPA/GdxlGyDKseQQAgIz5kzU7eXTrlSpA==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", + "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "node_modules/@sosuisen/api-documenter": { + "version": "7.13.27", + "resolved": "https://registry.npmjs.org/@sosuisen/api-documenter/-/api-documenter-7.13.27.tgz", + "integrity": "sha512-Y3uEwBRSbxEvlLXRD/YcaRhsVNVWMDRLE/EOVDAUzPYy5FrdXiNK0GZNdmxrjCe2E58W/bGKUTZnw9sOI2YOZg==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor-model": "^7.13.3", + "@microsoft/tsdoc": "^0.13.2", + "@rushstack/node-core-library": "^3.39.0", + "@rushstack/ts-command-line": "^4.7.10", + "colors": "~1.2.1", + "js-yaml": "~3.13.1", + "resolve": "~1.17.0" + }, + "bin": { + "api-documenter": "bin/api-documenter" + } + }, + "node_modules/@sosuisen/api-documenter/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@sosuisen/jsondiffpatch": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@sosuisen/jsondiffpatch/-/jsondiffpatch-0.4.7.tgz", + "integrity": "sha512-PBux/ylEnBMhB5WSee+Ql2YPrO5K7YEnfSm5aZufOEkmewkduakSWdmSrmreUGmJKQWLWqRGSpql3tl7YlppTQ==", + "dependencies": { + "chalk": "^2.3.0", + "diff-match-patch": "^1.0.0" + }, + "bin": { + "jsondiffpatch": "bin/jsondiffpatch" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/@sosuisen/nodegit": { + "version": "0.28.0-alpha.11", + "resolved": "https://registry.npmjs.org/@sosuisen/nodegit/-/nodegit-0.28.0-alpha.11.tgz", + "integrity": "sha512-mpztf9ncWxU7/agKQ6E7GvlBIa6H7m3YXuMjlPWVegHusqkbgPi4J01d2inCPhLz0CoC0F/L3LKJuDCAKDXJJg==", + "hasInstallScript": true, + "dependencies": { + "fs-extra": "^7.0.0", + "got": "^10.7.0", + "json5": "^2.1.0", + "lodash": "^4.17.14", + "nan": "^2.14.1", + "node-gyp": "^7.1.2", + "node-pre-gyp": "^0.13.0", + "ramda": "^0.25.0", + "tar-fs": "^1.16.3" + }, + "engines": { + "node": ">= 12.19.0 < 13 || >= 14.10.0" + } + }, + "node_modules/@sosuisen/nodegit/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@sosuisen/nodegit/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@sosuisen/nodegit/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "node_modules/@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true + }, + "node_modules/@types/async-lock": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.1.3.tgz", + "integrity": "sha512-UpeDcjGKsYEQMeqEbfESm8OWJI305I7b9KE4ji3aBjoKWyN5CTdn8izcA1FM1DVDne30R5fNEnIy89vZw5LXJQ==", + "dev": true + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "dev": true + }, + "node_modules/@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, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.3.tgz", + "integrity": "sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg==", + "dev": true + }, + "node_modules/@types/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", + "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.17.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.21.tgz", + "integrity": "sha512-zv8ukKci1mrILYiQOwGSV4FpkZhyxQtuFWGya2GujWg+zVAeRQ4qbaMmWp9vb9889CFA8JECH7lkwCL6Ygg8kA==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/parse-git-config": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/parse-git-config/-/parse-git-config-3.0.1.tgz", + "integrity": "sha512-cBVLXlpIpP23p+jQm8d2TrTfxyub3aiqfqgd0TWRnMqwCJMskYiveNJT11YwN+gbo3+0ZFFmtaepKzN7pxExlA==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", + "dev": true, + "dependencies": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sinon": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.11.tgz", + "integrity": "sha512-PwP4UY33SeeVKodNE37ZlOsR9cReypbMJOhZ7BVE0lB+Hix3efCOxiJWiE5Ia+yL9Cn2Ch72EjFTRze8RZsNtg==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz", + "integrity": "sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^4.0.0", + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", + "dev": true, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/angular-estree-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/angular-estree-parser/-/angular-estree-parser-1.3.1.tgz", + "integrity": "sha512-jvlnNk4aoEmA6EKK12OnsOkCSdsWleBsYB+aWyH8kpfTB6Li1kxWVbHKVldH9zDCwVVi1hXfqPi/gbSv49tkbQ==", + "dev": true, + "dependencies": { + "lines-and-columns": "^1.1.6", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "@angular/compiler": ">= 6.0.0 < 9.0.6" + } + }, + "node_modules/angular-html-parser": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/angular-html-parser/-/angular-html-parser-1.7.0.tgz", + "integrity": "sha512-/yjeqDQXGblZuFMI6vpDgiIDuv816QpIqa/mCotc0I4R0F5t5sfX1ntZ8VsBVQOUYRjPw8ggYlPZto76gHtf7Q==", + "dev": true, + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/are-we-there-yet/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "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" + } + }, + "node_modules/are-we-there-yet/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", + "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-lock": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.3.0.tgz", + "integrity": "sha512-8A7SkiisnEgME2zEedtDYPxUPzdv3x//E7n5IFktPAtMYSEAV7eNJF0rMwrVyUFj6d/8rgajLantbjcNRQYXIg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/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=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "node_modules/bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "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" + } + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/blob-polyfill": { + "version": "5.0.20210201", + "resolved": "https://registry.npmjs.org/blob-polyfill/-/blob-polyfill-5.0.20210201.tgz", + "integrity": "sha512-SrH6IG6aXL9pCgSysBCiDpGcAJ1j6/c1qCwR3sTEQJhb+MTk6FITNA6eW6WNYQDNZVi4Z9GjxH5v2MMTv59CrQ==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.3.tgz", + "integrity": "sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001264", + "electron-to-chromium": "^1.3.857", + "escalade": "^3.1.1", + "node-releases": "^1.1.77", + "picocolors": "^0.2.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-lookup": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz", + "integrity": "sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==", + "dependencies": { + "@types/keyv": "^3.1.1", + "keyv": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001338", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001338.tgz", + "integrity": "sha512-1gLHWyfVoRDsHieO+CaeYe7jSo/MT7D7lhaXUiwwbuR5BwQxORs0f1tAwUSQr3YbxRXJvxHM/PA5FfPQRnsPeQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/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 + }, + "node_modules/cjk-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cjk-regex/-/cjk-regex-2.0.0.tgz", + "integrity": "sha512-E4gFi2f3jC0zFVHpaAcupW+gv9OejZ2aV3DP/LlSO0dDcZJAXw7W0ivn+vN17edN/PhU4HCgs1bfx7lPK7FpdA==", + "dev": true, + "dependencies": { + "regexp-util": "^1.2.1", + "unicode-regex": "^2.0.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/cjk-regex/node_modules/unicode-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-2.0.0.tgz", + "integrity": "sha512-5nbEG2YU7loyTvPABaKb+8B0u8L7vWCsVmCSsiaO249ZdMKlvrXlxR2ex4TUVAdzv/Cne/TdoXSSaJArGXaleQ==", + "dev": true, + "dependencies": { + "regexp-util": "^1.2.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==" + }, + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/clone-response/node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/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==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/colors": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", + "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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 + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/compress-brotli": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.6.tgz", + "integrity": "sha512-au99/GqZtUtiCBliqLFbWlhnCxn+XSYjwZ77q6mKN4La4qOXDoLVPZ50iXr0WmAyMxl8yqoq3Yq4OeQNPPkyeQ==", + "dependencies": { + "@types/json-buffer": "~3.0.0", + "json-buffer": "~3.0.1" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/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=" + }, + "node_modules/cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/coveralls": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", + "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" + }, + "bin": { + "coveralls": "bin/coveralls.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/coveralls/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/crlf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/crlf/-/crlf-1.1.1.tgz", + "integrity": "sha1-JBcoQbTINSmmqkSJ337tlYsu0W8=", + "dev": true, + "dependencies": { + "glub": "^1.0.0", + "transform-file": "^1.0.1" + }, + "bin": { + "crlf": "bin/crlf" + } + }, + "node_modules/cross-blob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cross-blob/-/cross-blob-2.0.1.tgz", + "integrity": "sha512-ARuKPPo3I6DSqizal4UCyMCiGPQdMpMJS3Owx6Lleuh26vSt2UnfWRwbMLCYqbJUrcol+KzGVSLR91ezSHP80A==", + "dependencies": { + "blob-polyfill": "^5.0.20210201", + "fetch-blob": "^2.1.2" + }, + "engines": { + "node": "^10.17.0 || >=12.3.0" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dashify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", + "integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/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, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + }, + "node_modules/diff-sequences": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha1-1OXDpM305f4SEatC5pP8tDIVgPw=" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "dependencies": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "bin": { + "editorconfig": "bin/editorconfig" + } + }, + "node_modules/editorconfig-to-prettier": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/editorconfig-to-prettier/-/editorconfig-to-prettier-0.1.1.tgz", + "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==", + "dev": true + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.3.864", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz", + "integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/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==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/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=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-ast-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz", + "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==", + "dev": true, + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.zip": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-config-standard": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^7.12.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1 || ^5.0.0" + } + }, + "node_modules/eslint-config-standardize": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/eslint-config-standardize/-/eslint-config-standardize-0.7.2.tgz", + "integrity": "sha512-n2dt7la221Qig7FjQsrKn5NyK5jSEkkAy7xWSnY96XdG7H9FcUSDt5I1THyA6zHwEYcAtUFv8VOPBOK6oYEvfg==", + "dev": true, + "dependencies": { + "@jsbits/deep-clone": "~1.1.1", + "confusing-browser-globals": "*", + "deepmerge": "~4.2.2", + "eslint-config-standard": "~16.0.2", + "eslint-plugin-import": "~2.22.1", + "eslint-plugin-node": "~11.1.0", + "eslint-plugin-promise": "~4.2.1", + "eslint-plugin-react": "~7.22.0", + "eslint-plugin-react-hooks": "~4.2.0", + "eslint-plugin-unicorn": "~26.0.1" + }, + "bin": { + "list-eslint-config": "bin/list-eslint-config.js" + }, + "engines": { + "node": "^10.13.0 || >=12.0.0" + }, + "optionalDependencies": { + "@typescript-eslint/eslint-plugin": "^4.14.0", + "@typescript-eslint/parser": "^4.14.0" + }, + "peerDependencies": { + "eslint": ">=7.17.0" + } + }, + "node_modules/eslint-config-standardize/node_modules/eslint-plugin-unicorn": { + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-26.0.1.tgz", + "integrity": "sha512-SWgF9sIVY74zqkkSN2dclSCqRfocWSUGD0haC0NX2oRfmdp9p8dQvJYkYSQePaCyssPUE/pqpsIEEZNTh8crUA==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0", + "clean-regexp": "^1.0.0", + "eslint-ast-utils": "^1.1.0", + "eslint-template-visitor": "^2.2.2", + "eslint-utils": "^2.1.0", + "import-modules": "^2.1.0", + "lodash": "^4.17.20", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.21", + "reserved-words": "^0.1.2", + "safe-regex": "^2.1.1", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=7.17.0" + } + }, + "node_modules/eslint-config-standardize/node_modules/eslint-plugin-unicorn/node_modules/eslint-template-visitor": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz", + "integrity": "sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", + "eslint-visitor-keys": "^2.0.0", + "esquery": "^1.3.1", + "multimap": "^1.1.0" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-config-standardize/node_modules/eslint-plugin-unicorn/node_modules/eslint-template-visitor/node_modules/@babel/eslint-parser": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz", + "integrity": "sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==", + "dev": true, + "dependencies": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": ">=7.5.0" + } + }, + "node_modules/eslint-config-standardize/node_modules/eslint-plugin-unicorn/node_modules/eslint-template-visitor/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-standardize/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-config-standardize/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-config-standardize/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-config-standardize/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-config-standardize/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-config-standardize/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-config-standardize/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-config-standardize/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "pkg-dir": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-prettierx": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettierx/-/eslint-plugin-prettierx-0.14.0.tgz", + "integrity": "sha512-Ak/sI2LO0B73qEFjepPNUplxLadqpT3BU/I16ExZ0mY1CjpjoJxiyKe7Nbb0VEH4XO4SbjhngGPSsod+S3/HPA==", + "dev": true, + "dependencies": { + "eslint-config-prettier": "~6.11.0", + "prettier-linter-helpers": "~1.0.0", + "prettierx": "~0.14.0" + }, + "bin": { + "list-eslint-config": "bin/list-eslint-config.js" + }, + "engines": { + "node": "^10.13.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.2.0", + "typescript": ">=3.8.0" + } + }, + "node_modules/eslint-plugin-prettierx/node_modules/eslint-config-prettier": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", + "dev": true, + "dependencies": { + "get-stdin": "^6.0.0" + }, + "bin": { + "eslint-config-prettier-check": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=3.14.1" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", + "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-unicorn": { + "version": "36.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-36.0.0.tgz", + "integrity": "sha512-xxN2vSctGWnDW6aLElm/LKIwcrmk6mdiEcW55Uv5krcrVcIFSWMmEgc/hwpemYfZacKZ5npFERGNz4aThsp1AA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.9", + "ci-info": "^3.2.0", + "clean-regexp": "^1.0.0", + "eslint-template-visitor": "^2.3.2", + "eslint-utils": "^3.0.0", + "is-builtin-module": "^3.1.0", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.23", + "safe-regex": "^2.1.1", + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=7.32.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/ci-info": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "dev": true + }, + "node_modules/eslint-plugin-unicorn/node_modules/eslint-template-visitor": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz", + "integrity": "sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", + "eslint-visitor-keys": "^2.0.0", + "esquery": "^1.3.1", + "multimap": "^1.1.0" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/eslint-template-visitor/node_modules/@babel/eslint-parser": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz", + "integrity": "sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==", + "dev": true, + "dependencies": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": ">=7.5.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/eslint-template-visitor/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/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, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.2.5.tgz", + "integrity": "sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA==", + "dev": true, + "dependencies": { + "@jest/types": "^27.2.5", + "ansi-styles": "^5.0.0", + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-regex-util": "^27.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/expect/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==" + }, + "node_modules/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 + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fetch-blob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz", + "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==", + "engines": { + "node": "^10.17.0 || >=12.3.0" + }, + "peerDependenciesMeta": { + "domexception": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "node_modules/find-project-root": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/find-project-root/-/find-project-root-1.1.1.tgz", + "integrity": "sha1-0kJyei2QRyXfVxTyPf3N7doLbvg=", + "dev": true, + "bin": { + "find-project-root": "bin/find-project-root.js" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "node_modules/flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", + "dev": true + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/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==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "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" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/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, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/git-config-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-2.0.0.tgz", + "integrity": "sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/git-documentdb-plugin-remote-nodegit": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/git-documentdb-plugin-remote-nodegit/-/git-documentdb-plugin-remote-nodegit-1.0.4.tgz", + "integrity": "sha512-+esXlN6PMmvwKZPU6dn/kSQnVe5QHU9xGzoNrLiqehz+VM1AXgNhsce/KipimG4wdzUS6tbS9QbgIgA4VjpbAw==", + "dependencies": { + "@sosuisen/nodegit": "^0.28.0-alpha.11", + "git-documentdb-remote-errors": "^1.0.3", + "tslog": "^3.2.0" + } + }, + "node_modules/git-documentdb-remote-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-documentdb-remote-errors/-/git-documentdb-remote-errors-1.0.3.tgz", + "integrity": "sha512-14fN8VAQeBC7+Phs6TYB1D5PJDE/dF8dxbigKpsBEqR1FvpAQerSPptxVsQgkU33xwwZBOm7yCwVD2KKmQatOQ==" + }, + "node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glub": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/glub/-/glub-1.0.3.tgz", + "integrity": "sha1-VsFkMpiuJQZcYxUAMze7pp0vuGY=", + "dev": true, + "dependencies": { + "glob": "^5.0.5", + "minimist": "^1.1.1" + }, + "bin": { + "glub": "bin/glub" + } + }, + "node_modules/got": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", + "integrity": "sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==", + "dependencies": { + "@sindresorhus/is": "^2.0.0", + "@szmarczak/http-timer": "^4.0.0", + "@types/cacheable-request": "^6.0.1", + "cacheable-lookup": "^2.0.0", + "cacheable-request": "^7.0.1", + "decompress-response": "^5.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/type-fest": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, + "node_modules/graphql": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.3.0.tgz", + "integrity": "sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hmtid": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/hmtid/-/hmtid-0.1.0.tgz", + "integrity": "sha512-V+GXr9Q6ujl9zHQ+wUt66+H0HZ5KsvDuEWZ2l5cRRBGq1VRuz3THbObb0+eBrA1+H2Z6Vu0jTyMBICSqsDjQzA==", + "dev": true, + "bin": { + "hmtid": "bin/cli.js" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/html-element-attributes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/html-element-attributes/-/html-element-attributes-2.2.1.tgz", + "integrity": "sha512-gGTgCeQu+g1OFExZKWQ1LwbFXxLJ6cGdCGj64ByEaxatr/EPVc23D6Gxngb37ao+SNInP/sGu8FXxRsSxMm7aQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/html-styles/-/html-styles-1.0.0.tgz", + "integrity": "sha1-oYBh/WUfmca3XEXI4FSaO8PgGnU=", + "dev": true + }, + "node_modules/html-tag-names": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/html-tag-names/-/html-tag-names-1.1.5.tgz", + "integrity": "sha512-aI5tKwNTBzOZApHIynaAwecLBv8TlZTEy/P4Sj2SzzAhBrGuI8yGZ0UIXVPQzOHGS+to2mjb04iy6VWt/8+d8A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/is-builtin-module": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz", + "integrity": "sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", + "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-weakref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", + "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isomorphic-git": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.23.0.tgz", + "integrity": "sha512-7mQlnZivFwrU6B3CswvmoNtVN8jqF9BcLf80uk7yh4fNA8PhFjAfQigi2Hu/Io0cmIvpOc7vn0/Rq3KtL5Ph8g==", + "dependencies": { + "async-lock": "^1.1.0", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^3.4.0", + "sha.js": "^2.4.9", + "simple-get": "^4.0.1" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-0i77ZFLsb9U3DHi22WzmIngVzfoyxxbQcZRqlF3KoKmCJGq9nhFHoGi8FqBztN2rE8w6hURnZghetn0xpkVb6A==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.2.5.tgz", + "integrity": "sha512-7gfwwyYkeslOOVQY4tVq5TaQa92mWfC9COsVYMNVYyJTOYAqbIkoD3twi5A+h+tAPtAelRxkqY6/xu+jwTr0dA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-get-type": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz", + "integrity": "sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.2.5.tgz", + "integrity": "sha512-ggXSLoPfIYcbmZ8glgEJZ8b+e0Msw/iddRmgkoO7lDAr9SmI65IIfv7VnvTnV4FGnIIUIjzM+fHRHO5RBvyAbQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.2.5", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "pretty-format": "^27.2.5", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-regex-util": { + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, + "node_modules/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 + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/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==" + }, + "node_modules/json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "dependencies": { + "jsonify": "~0.0.0" + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/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=" + }, + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", + "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.3", + "object.assign": "^4.1.2" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "node_modules/keyv": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.2.2.tgz", + "integrity": "sha512-uYS0vKTlBIjNCAUqrjlxmruxOEiZxZIHXyp32sdcGmP+ukFrmWUnE//RcPXJH3Vxrni1H2gsQbjHE0bH7MtMQQ==", + "dependencies": { + "compress-brotli": "^1.3.6", + "json-buffer": "3.0.1" + } + }, + "node_modules/lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true, + "bin": { + "lcov-parse": "bin/cli.js" + } + }, + "node_modules/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, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/linguist-languages": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-7.10.0.tgz", + "integrity": "sha512-Uqt94P4iAznscZtccnNE1IBi105U+fmQKEUlDJv54JDdFZDInomkepEIRpZLOQcPyGdcNu3JO9Tvo5wpQVbfKw==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", + "dev": true + }, + "node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true, + "engines": { + "node": ">=0.8.6" + } + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/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 + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mem": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.1.tgz", + "integrity": "sha512-Ci6bIfq/UgcxPTYa8dQQ5FY3BzKkT894bwXWXxC/zqs0XgMO2cT20CGkOqda7gZNkmK5VP4x89IGZ6K7hfbn3Q==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", + "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", + "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "dependencies": { + "mime-db": "1.50.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "dependencies": { + "minimist": "^1.2.5" + } + }, + "node_modules/minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/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 + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multimap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz", + "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==", + "dev": true + }, + "node_modules/n-readlines": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/n-readlines/-/n-readlines-1.0.1.tgz", + "integrity": "sha512-z4SyAIVgMy7CkgsoNw7YVz40v0g4+WWvvqy8+ZdHrCtgevcEO758WQyrYcw3XPxcLxF+//RszTz/rO48nzD0wQ==", + "dev": true, + "engines": { + "node": ">=6.x.x" + } + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/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 + }, + "node_modules/needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-pre-gyp": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz", + "integrity": "sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "dependencies": { + "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" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/node-pre-gyp/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/node-pre-gyp/node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/node-pre-gyp/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-pre-gyp/node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/node-pre-gyp/node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/node-pre-gyp/node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/node-pre-gyp/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/node-pre-gyp/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/node-pre-gyp/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-pre-gyp/node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/node-pre-gyp/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "1.1.77", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", + "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", + "dev": true + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/nyc/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/ot-json1": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ot-json1/-/ot-json1-1.0.2.tgz", + "integrity": "sha512-IhxkqVWQqlkWULoi/Q2AdzKk0N5vQRbUMUwubFXFCPcY4TsOZjmp2YKrk0/z1TeiECPadWEK060sdFdQ3Grokg==", + "dependencies": { + "ot-text-unicode": "4" + } + }, + "node_modules/ot-text-unicode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ot-text-unicode/-/ot-text-unicode-4.0.0.tgz", + "integrity": "sha512-W7ZLU8QXesY2wagYFv47zErXud3E93FGImmSGJsQnBzE+idcPPyo2u2KMilIrTwBh4pbCizy71qRjmmV6aDhcQ==", + "dependencies": { + "unicount": "1.1" + } + }, + "node_modules/ot-text-unicode/node_modules/unicount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicount/-/unicount-1.1.0.tgz", + "integrity": "sha512-RlwWt1ywVW4WErPGAVHw/rIuJ2+MxvTME0siJ6lk9zBhpDfExDbspe6SRlWT3qU6AucNjotPl9qAJRVjP7guCQ==" + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dependencies": { + "p-timeout": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", + "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", + "dev": true, + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "node_modules/parse-git-config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-3.0.0.tgz", + "integrity": "sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA==", + "dev": true, + "dependencies": { + "git-config-path": "^2.0.0", + "ini": "^1.3.5" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/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, + "engines": { + "node": ">=4" + } + }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-less": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz", + "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "node_modules/postcss-scss": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz", + "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dev": true, + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettierx": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/prettierx/-/prettierx-0.14.3.tgz", + "integrity": "sha512-0VT3GgDAU6rvemeklrRzqVkILrGC1TSo/4STnsBqkreLx5Ck43W05lO60pMKWbG7SWM3DcUZZIR4FZ5pvvDwyQ==", + "dev": true, + "dependencies": { + "@angular/compiler": "9.0.5", + "@babel/code-frame": "7.12.11", + "@babel/parser": "7.12.0", + "@glimmer/syntax": "0.56.1", + "@iarna/toml": "2.2.5", + "@typescript-eslint/typescript-estree": "2.34.0", + "angular-estree-parser": "1.3.1", + "angular-html-parser": "1.7.0", + "camelcase": "6.2.0", + "chalk": "4.1.0", + "ci-info": "2.0.0", + "cjk-regex": "2.0.0", + "cosmiconfig": "7.0.0", + "dashify": "2.0.0", + "dedent": "0.7.0", + "diff": "4.0.2", + "editorconfig": "0.15.3", + "editorconfig-to-prettier": "0.1.1", + "escape-string-regexp": "4.0.0", + "esutils": "2.0.3", + "fast-glob": "3.2.4", + "find-parent-dir": "0.3.0", + "find-project-root": "1.1.1", + "get-stream": "6.0.0", + "globby": "11.0.1", + "graphql": "15.3.0", + "html-element-attributes": "2.2.1", + "html-styles": "1.0.0", + "html-tag-names": "1.1.5", + "ignore": "4.0.6", + "jest-docblock": "26.0.0", + "json-stable-stringify": "1.0.1", + "leven": "3.1.0", + "lines-and-columns": "1.1.6", + "linguist-languages": "7.10.0", + "lodash": "4.17.20", + "mem": "6.1.1", + "minimatch": "3.0.4", + "minimist": "1.2.5", + "n-readlines": "1.0.1", + "please-upgrade-node": "3.2.0", + "postcss-less": "3.1.4", + "postcss-media-query-parser": "0.2.3", + "postcss-scss": "2.1.1", + "postcss-selector-parser": "2.2.3", + "postcss-values-parser": "2.0.1", + "regexp-util": "1.2.2", + "remark-math": "1.0.6", + "remark-parse": "5.0.0", + "resolve": "1.19.0", + "semver": "7.3.4", + "srcset": "3.0.0", + "string-width": "4.2.0", + "tslib": "1.14.1", + "unicode-regex": "3.0.0", + "unified": "9.2.0", + "vnopts": "1.0.2", + "yaml-unist-parser": "1.3.1" + }, + "bin": { + "prettierx": "bin/prettierx.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependenciesMeta": { + "flow-parser": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/prettierx/node_modules/@babel/parser": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.0.tgz", + "integrity": "sha512-dYmySMYnlus2jwl7JnnajAj11obRStZoW9cG04wh4ZuhozDn11tDUrhHcUZ9iuNHqALAhh60XqNaYXpvuuE/Gg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettierx/node_modules/@typescript-eslint/typescript-estree": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", + "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/prettierx/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prettierx/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prettierx/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/prettierx/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/prettierx/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/prettierx/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/prettierx/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prettierx/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettierx/node_modules/fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettierx/node_modules/get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prettierx/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/prettierx/node_modules/globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prettierx/node_modules/globby/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/prettierx/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettierx/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/prettierx/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettierx/node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "node_modules/prettierx/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettierx/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/prettierx/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prettierx/node_modules/string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettierx/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prettierx/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/pretty-format": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.2.5.tgz", + "integrity": "sha512-+nYn2z9GgicO9JiqmY25Xtq8SYfZ/5VCpEU3pppHHNAhd1y+ZXxmNPd1evmNcAd6Hz4iBV2kf0UpGth5A/VJ7g==", + "dev": true, + "dependencies": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ramda": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", + "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "dependencies": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/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, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "dependencies": { + "pify": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", + "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", + "dev": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/regexp-util": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/regexp-util/-/regexp-util-1.2.2.tgz", + "integrity": "sha512-5/rl2UD18oAlLQEIuKBeiSIOp1hb5wCXcakl5yvHxlY1wyWI4D5cUKKzCibBeu741PA9JKvZhMqbkDQqPusX3w==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/remark-math": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-1.0.6.tgz", + "integrity": "sha512-I43wU/QOQpXvVFXKjA4FHp5xptK65+5F6yolm8+69/JV0EqSOB64wURUZ3JK50JtnTL8FvwLiH2PZ+fvsBxviA==", + "dev": true, + "dependencies": { + "trim-trailing-lines": "^1.1.0" + }, + "peerDependencies": { + "remark-parse": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "dev": true, + "dependencies": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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 + }, + "node_modules/reserved-words": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", + "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/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==" + }, + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "node_modules/signal-exit": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/simple-get/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/simple-html-tokenizer": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz", + "integrity": "sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og==", + "dev": true + }, + "node_modules/sinon": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.1.0", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/srcset": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-3.0.0.tgz", + "integrity": "sha512-D59vF08Qzu/C4GAOXVgMTLfgryt5fyWo93FZyhEWANo0PokFz/iWdDe13mX3O5TRf6l8vMTqckAfR4zPiaH0yQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "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" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz", + "integrity": "sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/table": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", + "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "dependencies": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/tar-fs/node_modules/pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tar-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "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" + } + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "node_modules/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, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-readable-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/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==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/transform-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/transform-file/-/transform-file-1.0.1.tgz", + "integrity": "sha1-f5WYSs0j1Ov4q7R+6dg74WbRJoc=", + "dev": true, + "dependencies": { + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "node_modules/trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-node": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz", + "integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "0.6.1", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tslog": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.2.2.tgz", + "integrity": "sha512-8dwb1cYpj3/w/MZTrSkPrdlA44loUodGT8N6ULMojqV4YByVM7ynhvVs9JwcIYxhhHf4bz1C5O3NKIPehnGp/w==", + "dependencies": { + "source-map-support": "^0.5.19" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", + "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.2.tgz", + "integrity": "sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ulid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", + "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", + "bin": { + "ulid": "bin/cli.js" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unicode-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unicode-regex/-/unicode-regex-3.0.0.tgz", + "integrity": "sha512-WiDJdORsqgxkZrjC8WsIP573130HNn7KsB0IDnUccW2BG2b19QQNloNhVe6DKk3Aef0UcoIHhNVj7IkkcYWrNw==", + "dev": true, + "dependencies": { + "regexp-util": "^1.2.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/unicount": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicount/-/unicount-1.2.0.tgz", + "integrity": "sha512-bbM0gwaKyIPll7smeeufgbN9sbJbrtr29o93HqF+4bzTeQcTN4zKtBKGwnLoGSG+E6gPQ/WL0t7xAhPKnWW4mQ==" + }, + "node_modules/unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dev": true, + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "node_modules/unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==", + "dev": true + }, + "node_modules/unist-util-remove-position": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", + "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "dev": true, + "dependencies": { + "unist-util-visit": "^1.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dev": true, + "dependencies": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dev": true, + "dependencies": { + "unist-util-is": "^3.0.0" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/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, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validator": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz", + "integrity": "sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vnopts": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vnopts/-/vnopts-1.0.2.tgz", + "integrity": "sha512-d2rr2EFhAGHnTlURu49G7GWmiJV80HbAnkYdD9IFAtfhmxC+kSWEaZ6ZF064DJFTv9lQZQV1vuLTntyQpoanGQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "leven": "^2.1.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/vnopts/node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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 + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yaml-unist-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/yaml-unist-parser/-/yaml-unist-parser-1.3.1.tgz", + "integrity": "sha512-4aHBMpYcnByF8l2OKj5hlBJlxSYIMON8Z1Hm57ymbBL4omXMlGgY+pEf4Di6h2qNT8ZG8seTVvAQYNOa7CZ9eA==", + "dev": true, + "dependencies": { + "lines-and-columns": "^1.1.6", + "tslib": "^1.10.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/z-schema": { + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.18.4.tgz", + "integrity": "sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw==", + "dev": true, + "dependencies": { + "lodash.get": "^4.0.0", + "lodash.isequal": "^4.0.0", + "validator": "^8.0.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "optionalDependencies": { + "commander": "^2.7.1" + } + } + }, + "dependencies": { + "@angular/compiler": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.5.tgz", + "integrity": "sha512-TeyhRGefTOtA9N3udMrvheafoXcz/dvTTdZLcieeZQxm1SSeaQDUQ/rUH6QTOiHVNMtjOCrZ9J5rk1A4mPYuag==", + "dev": true, + "requires": {} + }, + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "dev": true + }, + "@babel/core": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", + "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.15.8", + "@babel/generator": "^7.15.8", + "@babel/helper-compilation-targets": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.8", + "@babel/helpers": "^7.15.4", + "@babel/parser": "^7.15.8", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.6", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.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 + }, + "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.15.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", + "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", + "dev": true, + "requires": { + "@babel/types": "^7.15.6", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", + "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.15.0", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.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 + } + } + }, + "@babel/helper-function-name": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", + "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", + "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", + "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", + "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-module-imports": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", + "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", + "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.15.4", + "@babel/helper-replace-supers": "^7.15.4", + "@babel/helper-simple-access": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/helper-validator-identifier": "^7.15.7", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.6" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", + "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", + "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.15.4", + "@babel/helper-optimise-call-expression": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", + "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", + "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", + "dev": true, + "requires": { + "@babel/types": "^7.15.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true + }, + "@babel/helpers": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", + "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", + "dev": true, + "requires": { + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", + "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", + "dev": true + }, + "@babel/template": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + } + } + }, + "@babel/traverse": { + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", + "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.15.4", + "@babel/helper-function-name": "^7.15.4", + "@babel/helper-hoist-variables": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "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 + } + } + }, + "@babel/types": { + "version": "7.15.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", + "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.9", + "to-fast-properties": "^2.0.0" + } + }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "dev": true, + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } + } + }, + "@glimmer/env": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@glimmer/env/-/env-0.1.7.tgz", + "integrity": "sha1-/S0rVakCnGs3psk16MiHGucN+gc=", + "dev": true + }, + "@glimmer/interfaces": { + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/interfaces/-/interfaces-0.56.2.tgz", + "integrity": "sha512-nRgcsTuyZ90aEoCuYVHKGDs3LpAv9n/JKiJ6iecpEYtyGgcPqSI3GjrJRl6k+1s5wnldEH1kjWq+ccCiXmA99w==", + "dev": true, + "requires": { + "@simple-dom/interface": "^1.4.0" + } + }, + "@glimmer/syntax": { + "version": "0.56.1", + "resolved": "https://registry.npmjs.org/@glimmer/syntax/-/syntax-0.56.1.tgz", + "integrity": "sha512-4TdtIQVFo9UfIVzXnXpMuzsA4mX06oF9NER8FmIPjBosNiQsYB7P8sABSG+2rtWgsh6CkFXkwvxZ++BB+alwOw==", + "dev": true, + "requires": { + "@glimmer/interfaces": "^0.56.1", + "@glimmer/util": "^0.56.1", + "handlebars": "^4.7.4", + "simple-html-tokenizer": "^0.5.9" + } + }, + "@glimmer/util": { + "version": "0.56.2", + "resolved": "https://registry.npmjs.org/@glimmer/util/-/util-0.56.2.tgz", + "integrity": "sha512-AljXCX5HBjJkmNt4DNYmJmVvwqKjFF4lU6e0SBftwhzK85RbETYwpb3YWrghcjSCxoodwIu1zNFiKOA+xD6txw==", + "dev": true, + "requires": { + "@glimmer/env": "0.1.7", + "@glimmer/interfaces": "^0.56.2", + "@simple-dom/interface": "^1.4.0" + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "color-convert": "^2.0.1" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "path-parse": "^1.0.6" + "color-name": "~1.1.4" } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "has-flag": "^4.0.0" } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true } } }, + "@jsbits/deep-clone": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jsbits/deep-clone/-/deep-clone-1.1.1.tgz", + "integrity": "sha512-aKhOhRv18tlhkjapBrcyAt8U1SmyzKi2QoO4GGMlXRfQhwm7USDSo/pX8MgB8tYB3MLaevuvwufynKSDA7U3EA==", + "dev": true + }, + "@microsoft/api-extractor": { + "version": "7.18.15", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.18.15.tgz", + "integrity": "sha512-a8gPbb0gAO+gyWzGmB6eG9ACI3++JS0Y9049xKKITizbGV5PWrLlx3a5S1kSqVP7b6MxVK3QVnJskLzf8n1SkQ==", + "dev": true, + "requires": { + "@microsoft/api-extractor-model": "7.13.12", + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.42.2", + "@rushstack/rig-package": "0.3.2", + "@rushstack/ts-command-line": "4.10.1", + "colors": "~1.2.1", + "lodash": "~4.17.15", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "source-map": "~0.6.1", + "typescript": "~4.4.2" + } + }, "@microsoft/api-extractor-model": { - "version": "7.13.3", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.13.3.tgz", - "integrity": "sha512-uXilAhu2GcvyY/0NwVRk3AN7TFYjkPnjHLV2UywTTz9uglS+Af0YjNrCy+aaK8qXtfbFWdBzkH9N2XU8/YBeRQ==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.13.12.tgz", + "integrity": "sha512-BTTGg1tgcDpW3CyW6QQ3VWFLzKyHxfyNGw68EAS/MXnNKx580HE08hLWrSjM2zHQ1J35v4PBUorsRK+FBkHl5Q==", "dev": true, "requires": { "@microsoft/tsdoc": "0.13.2", "@microsoft/tsdoc-config": "~0.15.2", - "@rushstack/node-core-library": "3.39.0" + "@rushstack/node-core-library": "3.42.2" } }, "@microsoft/tsdoc": { @@ -534,56 +11218,60 @@ "resolve": "~1.19.0" }, "dependencies": { - "@microsoft/tsdoc": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", - "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", - "dev": true + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } } } }, "@nodelib/fs.scandir": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", - "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.4", + "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", - "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", - "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.4", + "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "@octokit/auth-token": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.5.tgz", - "integrity": "sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", "requires": { "@octokit/types": "^6.0.3" } }, "@octokit/core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.3.0.tgz", - "integrity": "sha512-GGMpjaodCBY7JrtOwfolMocwZw9Pj5NxuQqfaJhGau4tkyonm0JRV9D6juQYLMb1Kl261++4Q980o0FlAtg8jg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", "requires": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.4.12", + "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.0.5", "@octokit/types": "^6.0.3", "before-after-hook": "^2.2.0", @@ -591,85 +11279,70 @@ } }, "@octokit/endpoint": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", - "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", "requires": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - } } }, "@octokit/graphql": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.1.tgz", - "integrity": "sha512-2lYlvf4YTDgZCTXTW4+OX+9WTLFtEUc6hGm4qM1nlZjzxj+arizM4aHWzBVBCxY9glh7GIs0WEuiSgbVzv8cmA==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", "requires": { - "@octokit/request": "^5.3.0", + "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-5.3.2.tgz", - "integrity": "sha512-NxF1yfYOUO92rCx3dwvA2onF30Vdlg7YUkMVXkeptqpzA3tRLplThhFleV/UKWFgh7rpKu1yYRbvNDUtzSopKA==" + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" }, "@octokit/plugin-paginate-rest": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.11.0.tgz", - "integrity": "sha512-7L9xQank2G3r1dGqrVPo1z62V5utbykOUzlmNHPz87Pww/JpZQ9KyG5CHtUzgmB4n5iDRKYNK/86A8D98HP0yA==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz", + "integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==", "requires": { - "@octokit/types": "^6.11.0" + "@octokit/types": "^6.34.0" } }, "@octokit/plugin-request-log": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", - "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "4.13.5", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.13.5.tgz", - "integrity": "sha512-kYKcWkFm4Ldk8bZai2RVEP1z97k1C/Ay2FN9FNTBg7JIyKoiiJjks4OtT6cuKeZX39tqa+C3J9xeYc6G+6g8uQ==", + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz", + "integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==", "requires": { - "@octokit/types": "^6.12.2", + "@octokit/types": "^6.34.0", "deprecation": "^2.3.1" } }, "@octokit/request": { - "version": "5.4.14", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.14.tgz", - "integrity": "sha512-VkmtacOIQp9daSnBmDI92xNIeLuSRDOIuplp/CJomkvzt7M18NXgG044Cx/LFKLgjKt9T2tZR6AtJayba9GTSA==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz", + "integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==", "requires": { "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.0.0", - "@octokit/types": "^6.7.1", - "deprecation": "^2.0.0", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.1", - "once": "^1.4.0", "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - } } }, "@octokit/request-error": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", - "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "requires": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -677,31 +11350,31 @@ } }, "@octokit/rest": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.3.5.tgz", - "integrity": "sha512-ZPeRms3WhWxQBEvoIh0zzf8xdU2FX0Capa7+lTca8YHmRsO3QNJzf1H3PcuKKsfgp91/xVDRtX91sTe1kexlbw==", + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", "requires": { - "@octokit/core": "^3.2.3", - "@octokit/plugin-paginate-rest": "^2.6.2", - "@octokit/plugin-request-log": "^1.0.2", - "@octokit/plugin-rest-endpoint-methods": "4.13.5" + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" } }, "@octokit/types": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.12.2.tgz", - "integrity": "sha512-kCkiN8scbCmSq+gwdJV0iLgHc0O/GTPY1/cffo9kECu1MvatLPh9E+qFhfRIktKfHEA6ZYvv6S1B4Wnv3bi3pA==", + "version": "6.34.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", + "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", "requires": { - "@octokit/openapi-types": "^5.3.2" + "@octokit/openapi-types": "^11.2.0" } }, "@rushstack/node-core-library": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.39.0.tgz", - "integrity": "sha512-kgu3+7/zOBkZU0+NdJb1rcHcpk3/oTjn5c8cg5nUTn+JDjEw58yG83SoeJEcRNNdl11dGX0lKG2PxPsjCokZOQ==", + "version": "3.42.2", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.42.2.tgz", + "integrity": "sha512-LJ52CiiWxKpzejYACqphQQ3geWZFt5gswki8+0sMl8qZ08YCHbqlS3N+sMZpuBEwLWvBYfq/d3IvtdLT3zI2UA==", "dev": true, "requires": { - "@types/node": "10.17.13", + "@types/node": "12.20.24", "colors": "~1.2.1", "fs-extra": "~7.0.1", "import-lazy": "~4.0.0", @@ -713,9 +11386,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz", - "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==", + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", "dev": true }, "fs-extra": { @@ -738,24 +11411,6 @@ "graceful-fs": "^4.1.6" } }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -765,30 +11420,19 @@ } }, "@rushstack/rig-package": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.2.12.tgz", - "integrity": "sha512-nbePcvF8hQwv0ql9aeQxcaMPK/h1OLAC00W7fWCRWIvD2MchZOE8jumIIr66HGrfG2X1sw++m/ZYI4D+BM5ovQ==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.3.2.tgz", + "integrity": "sha512-lJbud9zBY8+OOjkeQ+4zIVCvt2I8y1C3WcVx3g6NJgjf0pi6IYfbAWXXG+mVzevQmqanNCLyhyXSNP3E6u5OvQ==", "dev": true, "requires": { "resolve": "~1.17.0", "strip-json-comments": "~3.1.1" - }, - "dependencies": { - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } } }, "@rushstack/ts-command-line": { - "version": "4.7.10", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.7.10.tgz", - "integrity": "sha512-8t042g8eerypNOEcdpxwRA3uCmz0duMo21rG4Z2mdz7JxJeylDmzjlU3wDdef2t3P1Z61JCdZB6fbm1Mh0zi7w==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.10.1.tgz", + "integrity": "sha512-FhWnQCjHtxmZr5sVEgoV1VHTFaPfJXQbVwujAaZUzuFfgqX+v2P9o0AXmUi/LED4tmPJp7A1nVgPx0ClyGUbWA==", "dev": true, "requires": { "@types/argparse": "1.0.38", @@ -809,9 +11453,9 @@ "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==" }, "@sinonjs/commons": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", - "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -844,9 +11488,9 @@ "dev": true }, "@sosuisen/api-documenter": { - "version": "7.13.25", - "resolved": "https://registry.npmjs.org/@sosuisen/api-documenter/-/api-documenter-7.13.25.tgz", - "integrity": "sha512-/BW6yDpP9DJGUtD/KD42DQR+Od7Gje1gAnrpwotwpEGhqCzAPyzZiV5z/1eegZfWbnmvtrPSbsCAtVkAhXmLZA==", + "version": "7.13.27", + "resolved": "https://registry.npmjs.org/@sosuisen/api-documenter/-/api-documenter-7.13.27.tgz", + "integrity": "sha512-Y3uEwBRSbxEvlLXRD/YcaRhsVNVWMDRLE/EOVDAUzPYy5FrdXiNK0GZNdmxrjCe2E58W/bGKUTZnw9sOI2YOZg==", "dev": true, "requires": { "@microsoft/api-extractor-model": "^7.13.3", @@ -867,15 +11511,6 @@ "argparse": "^1.0.7", "esprima": "^4.0.0" } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } } } }, @@ -886,65 +11521,19 @@ "requires": { "chalk": "^2.3.0", "diff-match-patch": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.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==", - "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=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } } }, "@sosuisen/nodegit": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@sosuisen/nodegit/-/nodegit-0.27.3.tgz", - "integrity": "sha512-0/SSdtXK+grdpbhJP116MtkyHWA1yJ+Tnnzsj5OEPj/bC5s9Losc52p8WKiDn1uKeJcN5F5Zg+VOx4vkBKD4dg==", + "version": "0.28.0-alpha.11", + "resolved": "https://registry.npmjs.org/@sosuisen/nodegit/-/nodegit-0.28.0-alpha.11.tgz", + "integrity": "sha512-mpztf9ncWxU7/agKQ6E7GvlBIa6H7m3YXuMjlPWVegHusqkbgPi4J01d2inCPhLz0CoC0F/L3LKJuDCAKDXJJg==", "requires": { "fs-extra": "^7.0.0", "got": "^10.7.0", "json5": "^2.1.0", "lodash": "^4.17.14", - "nan": "^2.14.0", - "node-gyp": "^4.0.0", + "nan": "^2.14.1", + "node-gyp": "^7.1.2", "node-pre-gyp": "^0.13.0", "ramda": "^0.25.0", "tar-fs": "^1.16.3" @@ -976,13 +11565,37 @@ } }, "@szmarczak/http-timer": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", - "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "requires": { "defer-to-connect": "^2.0.0" } }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, "@types/argparse": { "version": "1.0.38", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", @@ -990,14 +11603,15 @@ "dev": true }, "@types/async-lock": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.1.2.tgz", - "integrity": "sha512-j9n4bb6RhgFIydBe0+kpjnBPYumDaDyU8zvbWykyVMkku+c2CSu31MZkLeaBfqIwU+XCxlDpYDfyMQRkM0AkeQ==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/async-lock/-/async-lock-1.1.3.tgz", + "integrity": "sha512-UpeDcjGKsYEQMeqEbfESm8OWJI305I7b9KE4ji3aBjoKWyN5CTdn8izcA1FM1DVDne30R5fNEnIy89vZw5LXJQ==", + "dev": true }, "@types/cacheable-request": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", - "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", "requires": { "@types/http-cache-semantics": "*", "@types/keyv": "*", @@ -1005,35 +11619,19 @@ "@types/responselike": "*" } }, - "@types/eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", - "dev": true, - "optional": true - }, - "@types/expect": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-24.3.0.tgz", - "integrity": "sha512-aq5Z+YFBz5o2b6Sp1jigx5nsmoZMK5Ceurjwy6PZmRv7dEi1jLtkARfvB1ME+OXJUG+7TZUDcv3WoCr/aor6dQ==", - "dev": true, - "requires": { - "expect": "*" - } - }, "@types/fs-extra": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.6.tgz", - "integrity": "sha512-ecNRHw4clCkowNOBJH1e77nvbPxHYnWIXMv1IAoG/9+MYGkgoyr3Ppxr7XYFNL41V422EDhyV4/4SSK8L2mlig==", + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dev": true, "requires": { "@types/node": "*" } }, "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", "dev": true, "requires": { "@types/minimatch": "*", @@ -1041,9 +11639,9 @@ } }, "@types/http-cache-semantics": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", - "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "@types/istanbul-lib-coverage": { "version": "2.0.3", @@ -1069,12 +11667,22 @@ "@types/istanbul-lib-report": "*" } }, + "@types/js-yaml": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.3.tgz", + "integrity": "sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg==", + "dev": true + }, + "@types/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==" + }, "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true, - "optional": true + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true }, "@types/json5": { "version": "0.0.29", @@ -1083,40 +11691,40 @@ "dev": true }, "@types/keyv": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", - "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "requires": { "@types/node": "*" } }, "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, "@types/mocha": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", - "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", + "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", "dev": true }, "@types/node": { - "version": "14.14.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", - "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==" + "version": "14.17.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.21.tgz", + "integrity": "sha512-zv8ukKci1mrILYiQOwGSV4FpkZhyxQtuFWGya2GujWg+zVAeRQ4qbaMmWp9vb9889CFA8JECH7lkwCL6Ygg8kA==" }, "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, "@types/parse-git-config": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-git-config/-/parse-git-config-3.0.0.tgz", - "integrity": "sha512-5C14/81ohSwjB5I0EweuG3qyn6CqgVOgk9orxHDwVvUdDbS4FMXANXnKz3CA3H2Jk2oa3vzMEpXtDQ5u0dCcTQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/parse-git-config/-/parse-git-config-3.0.1.tgz", + "integrity": "sha512-cBVLXlpIpP23p+jQm8d2TrTfxyub3aiqfqgd0TWRnMqwCJMskYiveNJT11YwN+gbo3+0ZFFmtaepKzN7pxExlA==", "dev": true }, "@types/parse-json": { @@ -1134,9 +11742,9 @@ } }, "@types/rimraf": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.0.tgz", - "integrity": "sha512-7WhJ0MdpFgYQPXlF4Dx+DhgvlPCfz/x5mHaeDQAKhcenvQP1KCpLQ18JklAqeGMYSAT2PxLpzd0g2/HE7fj7hQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==", "dev": true, "requires": { "@types/glob": "*", @@ -1153,273 +11761,129 @@ } }, "@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.4.tgz", + "integrity": "sha512-IFQTJARgMUBF+xVd2b+hIgXWrZEjND3vJtRCvIelcFB5SIXfjV4bOHbHJ0eXKh+0COrBRc8MqteKAz/j88rE0A==", "dev": true }, "@types/stack-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", - "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", "dev": true }, "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "20.2.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", - "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz", - "integrity": "sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.28.0", - "@typescript-eslint/scope-manager": "4.28.0", + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", - "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0" - } - }, - "@typescript-eslint/types": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", - "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", - "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.28.0", - "eslint-visitor-keys": "^2.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz", - "integrity": "sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.0", - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/typescript-estree": "4.28.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", - "dev": true - }, - "@typescript-eslint/scope-manager": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", - "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0" - } - }, - "@typescript-eslint/types": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", - "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz", - "integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", - "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.28.0", - "eslint-visitor-keys": "^2.0.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "requires": { - "tslib": "^1.8.1" + "eslint-visitor-keys": "^2.0.0" } } } }, "@typescript-eslint/parser": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.0.tgz", - "integrity": "sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.28.0", - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/typescript-estree": "4.28.0", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", "debug": "^4.3.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", - "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0" + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" } }, "@typescript-eslint/types": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", - "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz", - "integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", "semver": "^7.3.5", "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } } }, "@typescript-eslint/visitor-keys": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", - "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.0", + "@typescript-eslint/types": "4.33.0", "eslint-visitor-keys": "^2.0.0" } }, @@ -1441,9 +11905,16 @@ "dev": true }, "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true }, "aggregate-error": { @@ -1493,24 +11964,23 @@ "dev": true }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "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==", "requires": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -1538,12 +12008,41 @@ "dev": true }, "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "arg": { @@ -1562,16 +12061,16 @@ } }, "array-includes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", - "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "get-intrinsic": "^1.0.1", - "is-string": "^1.0.5" + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" } }, "array-union": { @@ -1581,26 +12080,25 @@ "dev": true }, "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "es-abstract": "^1.19.0" } }, "array.prototype.flatmap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", - "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", + "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "function-bind": "^1.1.1" + "es-abstract": "^1.19.0" } }, "asn1": { @@ -1647,28 +12145,6 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, - "babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, "bail": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", @@ -1676,9 +12152,9 @@ "dev": true }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -1689,9 +12165,9 @@ } }, "before-after-hook": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.0.tgz", - "integrity": "sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, "binary-extensions": { "version": "2.2.0", @@ -1706,12 +12182,41 @@ "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "blob-polyfill": { - "version": "4.0.20200601", - "resolved": "https://registry.npmjs.org/blob-polyfill/-/blob-polyfill-4.0.20200601.tgz", - "integrity": "sha512-1jB6WOIp6IDxNyng5+9A8g/f0uiphib2ELCN+XAnlssinsW8s1k4VYG9b1TxIUd3pdm9RJSLQuBh6iohYmD4hA==" + "version": "5.0.20210201", + "resolved": "https://registry.npmjs.org/blob-polyfill/-/blob-polyfill-5.0.20210201.tgz", + "integrity": "sha512-SrH6IG6aXL9pCgSysBCiDpGcAJ1j6/c1qCwR3sTEQJhb+MTk6FITNA6eW6WNYQDNZVi4Z9GjxH5v2MMTv59CrQ==" }, "brace-expansion": { "version": "1.1.11", @@ -1737,6 +12242,19 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserslist": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.3.tgz", + "integrity": "sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001264", + "electron-to-chromium": "^1.3.857", + "escalade": "^3.1.1", + "node-releases": "^1.1.77", + "picocolors": "^0.2.1" + } + }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", @@ -1757,9 +12275,15 @@ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, "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==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true }, "cacheable-lookup": { "version": "2.0.1", @@ -1771,27 +12295,17 @@ } }, "cacheable-request": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", - "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", + "normalize-url": "^6.0.1", "responselike": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - } } }, "caching-transform": { @@ -1807,13 +12321,13 @@ } }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, "callsites": { @@ -1828,19 +12342,25 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001338", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001338.tgz", + "integrity": "sha512-1gLHWyfVoRDsHieO+CaeYe7jSo/MT7D7lhaXUiwwbuR5BwQxORs0f1tAwUSQr3YbxRXJvxHM/PA5FfPQRnsPeQ==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "character-entities": { @@ -1878,9 +12398,9 @@ } }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "ci-info": { "version": "2.0.0", @@ -1930,14 +12450,33 @@ "dev": true }, "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } } }, "clone-response": { @@ -1967,19 +12506,17 @@ "dev": true }, "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { "version": "1.2.5", @@ -2007,6 +12544,15 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compress-brotli": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.6.tgz", + "integrity": "sha512-au99/GqZtUtiCBliqLFbWlhnCxn+XSYjwZ77q6mKN4La4qOXDoLVPZ50iXr0WmAyMxl8yqoq3Yq4OeQNPPkyeQ==", + "requires": { + "@types/json-buffer": "~3.0.0", + "json-buffer": "~3.0.1" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2030,9 +12576,9 @@ "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==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -2057,9 +12603,9 @@ } }, "coveralls": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", - "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", + "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", "dev": true, "requires": { "js-yaml": "^3.13.1", @@ -2067,16 +12613,24 @@ "log-driver": "^1.2.7", "minimist": "^1.2.5", "request": "^2.88.2" + }, + "dependencies": { + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } } }, "crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", - "requires": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" - } + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" }, "create-require": { "version": "1.1.1", @@ -2095,12 +12649,12 @@ } }, "cross-blob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cross-blob/-/cross-blob-2.0.0.tgz", - "integrity": "sha512-NWzFuyG4GTZnM9MtQvjPYVlO12lZCSBdoHIHCZl9WKShsK3CqO+bEH7nuKwlVomlByb37XvT6nVY5uQxDBmk5Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cross-blob/-/cross-blob-2.0.1.tgz", + "integrity": "sha512-ARuKPPo3I6DSqizal4UCyMCiGPQdMpMJS3Owx6Lleuh26vSt2UnfWRwbMLCYqbJUrcol+KzGVSLR91ezSHP80A==", "requires": { - "blob-polyfill": "^4.0.20200601", - "fetch-blob": "^2.0.1" + "blob-polyfill": "^5.0.20210201", + "fetch-blob": "^2.1.2" } }, "cross-env": { @@ -2110,49 +12664,17 @@ "dev": true, "requires": { "cross-spawn": "^7.0.1" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, "dashdash": { @@ -2170,9 +12692,9 @@ "dev": true }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -2204,9 +12726,9 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "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=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "deepmerge": { @@ -2225,9 +12747,9 @@ } }, "defer-to-connect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", - "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" }, "define-properties": { "version": "1.1.3", @@ -2265,9 +12787,9 @@ "dev": true }, "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "diff-match-patch": { @@ -2276,9 +12798,9 @@ "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" }, "diff-sequences": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", - "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", + "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", "dev": true }, "diff3": { @@ -2330,20 +12852,10 @@ "sigmund": "^1.0.1" }, "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } @@ -2354,6 +12866,12 @@ "integrity": "sha512-MMadSSVRDb4uKdxV6bCXXN4cTsxIsXYtV4XdPu6FOCSAw6zsCIDA+QEktEU+u6h+c/mTrul5NR+pwFpPxwetiQ==", "dev": true }, + "electron-to-chromium": { + "version": "1.3.864", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz", + "integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2377,6 +12895,11 @@ "ansi-colors": "^4.1.1" } }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2387,23 +12910,31 @@ } }, "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, "es-to-primitive": { @@ -2435,29 +12966,32 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz", - "integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.2", + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -2465,7 +12999,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -2474,113 +13008,80 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^6.0.4", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "color-convert": "^2.0.1" } }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "color-name": "~1.1.4" } }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "prelude-ls": "^1.2.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "isexe": "^2.0.0" + "has-flag": "^4.0.0" } } } @@ -2595,260 +13096,216 @@ "lodash.zip": "^4.2.0" } }, - "eslint-config-prettier": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", - "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", - "dev": true, - "requires": { - "get-stdin": "^6.0.0" - } - }, "eslint-config-standard": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz", - "integrity": "sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==", - "dev": true + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", + "dev": true, + "requires": {} }, "eslint-config-standardize": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/eslint-config-standardize/-/eslint-config-standardize-0.7.1.tgz", - "integrity": "sha512-8tut4nppZ+kpOHPa/AG8Wzr/HAEmNGnJXrGa10dCBKmNGaBsXtLkYL1hb1s80EGyw1JchIyHOpy/z9vHWeqAeQ==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/eslint-config-standardize/-/eslint-config-standardize-0.7.2.tgz", + "integrity": "sha512-n2dt7la221Qig7FjQsrKn5NyK5jSEkkAy7xWSnY96XdG7H9FcUSDt5I1THyA6zHwEYcAtUFv8VOPBOK6oYEvfg==", "dev": true, "requires": { "@jsbits/deep-clone": "~1.1.1", - "@typescript-eslint/eslint-plugin": "~3.9.0", - "@typescript-eslint/parser": "~3.9.0", + "@typescript-eslint/eslint-plugin": "^4.14.0", + "@typescript-eslint/parser": "^4.14.0", "confusing-browser-globals": "*", "deepmerge": "~4.2.2", - "eslint-config-standard": "~14.1.1", - "eslint-plugin-import": "~2.22.0", + "eslint-config-standard": "~16.0.2", + "eslint-plugin-import": "~2.22.1", "eslint-plugin-node": "~11.1.0", "eslint-plugin-promise": "~4.2.1", - "eslint-plugin-react": "~7.20.5", - "eslint-plugin-react-hooks": "~4.0.8", - "eslint-plugin-standard": "~4.0.1", - "eslint-plugin-unicorn": "~21.0.0" + "eslint-plugin-react": "~7.22.0", + "eslint-plugin-react-hooks": "~4.2.0", + "eslint-plugin-unicorn": "~26.0.1" }, "dependencies": { - "@typescript-eslint/eslint-plugin": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.9.1.tgz", - "integrity": "sha512-XIr+Mfv7i4paEdBf0JFdIl9/tVxyj+rlilWIfZ97Be0lZ7hPvUbS5iHt9Glc8kRI53dsr0PcAEudbf8rO2wGgg==", + "eslint-plugin-unicorn": { + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-26.0.1.tgz", + "integrity": "sha512-SWgF9sIVY74zqkkSN2dclSCqRfocWSUGD0haC0NX2oRfmdp9p8dQvJYkYSQePaCyssPUE/pqpsIEEZNTh8crUA==", "dev": true, - "optional": true, "requires": { - "@typescript-eslint/experimental-utils": "3.9.1", - "debug": "^4.1.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" + "ci-info": "^2.0.0", + "clean-regexp": "^1.0.0", + "eslint-ast-utils": "^1.1.0", + "eslint-template-visitor": "^2.2.2", + "eslint-utils": "^2.1.0", + "import-modules": "^2.1.0", + "lodash": "^4.17.20", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.21", + "reserved-words": "^0.1.2", + "safe-regex": "^2.1.1", + "semver": "^7.3.4" + }, + "dependencies": { + "eslint-template-visitor": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz", + "integrity": "sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", + "eslint-visitor-keys": "^2.0.0", + "esquery": "^1.3.1", + "multimap": "^1.1.0" + }, + "dependencies": { + "@babel/eslint-parser": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz", + "integrity": "sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==", + "dev": true, + "requires": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + } } }, - "@typescript-eslint/experimental-utils": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.1.tgz", - "integrity": "sha512-lkiZ8iBBaYoyEKhCkkw4SAeatXyBq9Ece5bZXdLe1LWBUwTszGbmbiqmQbwWA8cSYDnjWXp9eDbXpf9Sn0hLAg==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "optional": true, "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/types": "3.9.1", - "@typescript-eslint/typescript-estree": "3.9.1", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "@typescript-eslint/parser": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.9.1.tgz", - "integrity": "sha512-y5QvPFUn4Vl4qM40lI+pNWhTcOWtpZAJ8pOEQ21fTTW4xTJkRplMjMRje7LYTXqVKKX9GJhcyweMz2+W1J5bMg==", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "optional": true, "requires": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.9.1", - "@typescript-eslint/types": "3.9.1", - "@typescript-eslint/typescript-estree": "3.9.1", - "eslint-visitor-keys": "^1.1.0" + "p-locate": "^4.1.0" } }, - "@typescript-eslint/types": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.9.1.tgz", - "integrity": "sha512-15JcTlNQE1BsYy5NBhctnEhEoctjXOjOK+Q+rk8ugC+WXU9rAcS2BYhoh6X4rOaXJEpIYDl+p7ix+A5U0BqPTw==", - "dev": true, - "optional": true - }, - "@typescript-eslint/typescript-estree": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.1.tgz", - "integrity": "sha512-IqM0gfGxOmIKPhiHW/iyAEXwSVqMmR2wJ9uXHNdFpqVvPaQ3dWg302vW127sBpAiqM9SfHhyS40NKLsoMpN2KA==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "optional": true, "requires": { - "@typescript-eslint/types": "3.9.1", - "@typescript-eslint/visitor-keys": "3.9.1", - "debug": "^4.1.1", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" + "p-try": "^2.0.0" } }, - "@typescript-eslint/visitor-keys": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.1.tgz", - "integrity": "sha512-zxdtUjeoSh+prCpogswMwVUJfEFmCOjdzK9rpNjNBfm6EyPt99x3RrJoBOGZO23FCt0WPKUCOL5mb/9D5LjdwQ==", + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "optional": true, "requires": { - "eslint-visitor-keys": "^1.1.0" + "p-limit": "^2.2.0" } }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, - "optional": true + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } }, - "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, - "optional": true, "requires": { - "lru-cache": "^6.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } } } }, "eslint-module-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", - "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", "dev": true, "requires": { - "debug": "^2.6.9", + "debug": "^3.2.7", "pkg-dir": "^2.0.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "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 - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "find-up": "^2.1.0" + "ms": "^2.1.1" } } } }, - "eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - } - }, "eslint-plugin-import": { "version": "2.22.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", @@ -2880,99 +13337,26 @@ } }, "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "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-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, - "read-pkg-up": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -2990,6 +13374,16 @@ "semver": "^6.1.0" }, "dependencies": { + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -3007,6 +13401,17 @@ "eslint-config-prettier": "~6.11.0", "prettier-linter-helpers": "~1.0.0", "prettierx": "~0.14.0" + }, + "dependencies": { + "eslint-config-prettier": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + } } }, "eslint-plugin-promise": { @@ -3016,21 +13421,21 @@ "dev": true }, "eslint-plugin-react": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.6.tgz", - "integrity": "sha512-kidMTE5HAEBSLu23CUDvj8dc3LdBU0ri1scwHBZjI41oDv4tjsWZKU7MQccFzH1QYPYhsnTF2ovh7JlcIcmxgg==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", "dev": true, "requires": { "array-includes": "^3.1.1", "array.prototype.flatmap": "^1.2.3", "doctrine": "^2.1.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", "object.entries": "^1.1.2", "object.fromentries": "^2.0.2", "object.values": "^1.1.1", "prop-types": "^15.7.2", - "resolve": "^1.17.0", + "resolve": "^1.18.1", "string.prototype.matchall": "^4.0.2" }, "dependencies": { @@ -3042,59 +13447,166 @@ "requires": { "esutils": "^2.0.2" } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } } } }, "eslint-plugin-react-hooks": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.0.8.tgz", - "integrity": "sha512-6SSb5AiMCPd8FDJrzah+Z4F44P2CdOaK026cXFV+o/xSRzfOiV1FNFeLl2z6xm3yqWOQEZ5OfVgiec90qV2xrQ==", - "dev": true - }, - "eslint-plugin-standard": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.2.tgz", - "integrity": "sha512-nKptN8l7jksXkwFk++PhJB3cCDTcXOEyhISIN86Ue2feJ1LFyY3PrY3/xT2keXlJSY5bpmbiTG0f885/YKAvTA==", - "dev": true + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", + "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", + "dev": true, + "requires": {} }, "eslint-plugin-unicorn": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-21.0.0.tgz", - "integrity": "sha512-S8v7+v4gZTQPj4pKKvexhgSUaLQSyItvxW2SVZDaX9Iu5IjlAmF2eni+L6w8a2aqshxgU8Lle4FIAVDtuejSKQ==", + "version": "36.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-36.0.0.tgz", + "integrity": "sha512-xxN2vSctGWnDW6aLElm/LKIwcrmk6mdiEcW55Uv5krcrVcIFSWMmEgc/hwpemYfZacKZ5npFERGNz4aThsp1AA==", "dev": true, "requires": { - "ci-info": "^2.0.0", + "@babel/helper-validator-identifier": "^7.14.9", + "ci-info": "^3.2.0", "clean-regexp": "^1.0.0", - "eslint-ast-utils": "^1.1.0", - "eslint-template-visitor": "^2.0.0", - "eslint-utils": "^2.1.0", - "import-modules": "^2.0.0", - "lodash": "^4.17.15", + "eslint-template-visitor": "^2.3.2", + "eslint-utils": "^3.0.0", + "is-builtin-module": "^3.1.0", + "lodash": "^4.17.21", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", - "regexp-tree": "^0.1.21", - "reserved-words": "^0.1.2", + "regexp-tree": "^0.1.23", "safe-regex": "^2.1.1", - "semver": "^7.3.2" + "semver": "^7.3.5" }, "dependencies": { - "safe-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", - "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "ci-info": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "dev": true + }, + "eslint-template-visitor": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz", + "integrity": "sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==", "dev": true, "requires": { - "regexp-tree": "~0.1.1" + "@babel/core": "^7.12.16", + "@babel/eslint-parser": "^7.12.16", + "eslint-visitor-keys": "^2.0.0", + "esquery": "^1.3.1", + "multimap": "^1.1.0" + }, + "dependencies": { + "@babel/eslint-parser": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz", + "integrity": "sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==", + "dev": true, + "requires": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "eslint-visitor-keys": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, @@ -3108,18 +13620,6 @@ "estraverse": "^4.1.1" } }, - "eslint-template-visitor": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/eslint-template-visitor/-/eslint-template-visitor-2.2.2.tgz", - "integrity": "sha512-SkcLjzKw3JjKTWHacRDeLBa2gxb600zbCKTkXj/V97QnZ9yxkknoPL8vc8PFueqbFXP7mYNTQzjCjcMpTRdRaA==", - "dev": true, - "requires": { - "babel-eslint": "^10.1.0", - "eslint-visitor-keys": "^2.0.0", - "esquery": "^1.3.1", - "multimap": "^1.1.0" - } - }, "eslint-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", @@ -3138,9 +13638,9 @@ } }, "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true }, "espree": { @@ -3169,9 +13669,9 @@ "dev": true }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -3214,23 +13714,18 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "exit-on-epipe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", - "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" - }, "expect": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", - "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.2.5.tgz", + "integrity": "sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA==", "dev": true, "requires": { - "@jest/types": "^27.0.2", + "@jest/types": "^27.2.5", "ansi-styles": "^5.0.0", - "jest-get-type": "^27.0.1", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-regex-util": "^27.0.1" + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-regex-util": "^27.0.6" }, "dependencies": { "ansi-styles": { @@ -3263,17 +13758,16 @@ "dev": true }, "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", + "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "micromatch": "^4.0.4" } }, "fast-json-stable-stringify": { @@ -3288,9 +13782,9 @@ "dev": true }, "fastq": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", - "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -3302,9 +13796,9 @@ "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==" }, "file-entry-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", - "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { "flat-cache": "^3.0.4" @@ -3320,14 +13814,62 @@ } }, "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "requires": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + } } }, "find-parent-dir": { @@ -3343,12 +13885,12 @@ "dev": true }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, @@ -3369,9 +13911,9 @@ } }, "flatted": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", - "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", "dev": true }, "flatten": { @@ -3388,49 +13930,6 @@ "requires": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "forever-agent": { @@ -3471,11 +13970,11 @@ } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" } }, "fs.realpath": { @@ -3522,24 +14021,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -3563,9 +14044,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { "function-bind": "^1.1.1", @@ -3585,6 +14066,24 @@ "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -3599,33 +14098,51 @@ "integrity": "sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==", "dev": true }, + "git-documentdb-plugin-remote-nodegit": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/git-documentdb-plugin-remote-nodegit/-/git-documentdb-plugin-remote-nodegit-1.0.4.tgz", + "integrity": "sha512-+esXlN6PMmvwKZPU6dn/kSQnVe5QHU9xGzoNrLiqehz+VM1AXgNhsce/KipimG4wdzUS6tbS9QbgIgA4VjpbAw==", + "requires": { + "@sosuisen/nodegit": "^0.28.0-alpha.11", + "git-documentdb-remote-errors": "^1.0.3", + "tslog": "^3.2.0" + } + }, + "git-documentdb-remote-errors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-documentdb-remote-errors/-/git-documentdb-remote-errors-1.0.3.tgz", + "integrity": "sha512-14fN8VAQeBC7+Phs6TYB1D5PJDE/dF8dxbigKpsBEqR1FvpAQerSPptxVsQgkU33xwwZBOm7yCwVD2KKmQatOQ==" + }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, "requires": { - "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "2 || 3", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" } }, "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 + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } }, "globby": { "version": "11.0.4", @@ -3641,29 +14158,14 @@ "slash": "^3.0.0" } }, - "glub": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/glub/-/glub-1.0.3.tgz", - "integrity": "sha1-VsFkMpiuJQZcYxUAMze7pp0vuGY=", - "dev": true, - "requires": { - "glob": "^5.0.5", - "minimist": "^1.1.1" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } + "glub": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/glub/-/glub-1.0.3.tgz", + "integrity": "sha1-VsFkMpiuJQZcYxUAMze7pp0vuGY=", + "dev": true, + "requires": { + "glob": "^5.0.5", + "minimist": "^1.1.1" } }, "got": { @@ -3688,14 +14190,6 @@ "type-fest": "^0.10.0" }, "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, "type-fest": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", @@ -3704,9 +14198,9 @@ } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "graphql": { "version": "15.3.0", @@ -3721,9 +14215,9 @@ "dev": true }, "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { "minimist": "^1.2.5", @@ -3756,18 +14250,32 @@ "function-bind": "^1.1.1" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", "dev": true }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, "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==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3783,10 +14291,10 @@ "type-fest": "^0.8.0" }, "dependencies": { - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true } } @@ -3797,10 +14305,16 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hmtid": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/hmtid/-/hmtid-0.1.0.tgz", + "integrity": "sha512-V+GXr9Q6ujl9zHQ+wUt66+H0HZ5KsvDuEWZ2l5cRRBGq1VRuz3THbObb0+eBrA1+H2Z6Vu0jTyMBICSqsDjQzA==", + "dev": true + }, "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==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "html-element-attributes": { @@ -3856,9 +14370,9 @@ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", "requires": { "minimatch": "^3.0.4" } @@ -3871,14 +14385,6 @@ "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } } }, "import-lazy": { @@ -3931,35 +14437,14 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dev": true, "requires": { - "es-abstract": "^1.17.0-next.1", + "get-intrinsic": "^1.1.0", "has": "^1.0.3", - "side-channel": "^1.0.2" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "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.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "side-channel": "^1.0.4" } }, "is-alphabetical": { @@ -3984,6 +14469,15 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3993,26 +14487,54 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + }, + "is-builtin-module": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.1.0.tgz", + "integrity": "sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg==", + "dev": true, + "requires": { + "builtin-modules": "^3.0.0" + } + }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", + "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", "dev": true, "requires": { "has": "^1.0.3" } }, "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 + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-decimal": { "version": "1.0.4", @@ -4027,15 +14549,17 @@ "dev": true }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -4059,34 +14583,64 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "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==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-typedarray": { @@ -4094,6 +14648,15 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-weakref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", + "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-whitespace-character": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", @@ -4113,9 +14676,10 @@ "dev": true }, "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true }, "isexe": { "version": "2.0.0", @@ -4123,9 +14687,9 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isomorphic-git": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.8.2.tgz", - "integrity": "sha512-wp3on2Kks1sE/tLUmGLPV7EEAj+JRK8WoL2ZSfJHVQfWzRqMRv96bqzDjyYpC6COGKlDQnhTNCucRf83S3cuMw==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.23.0.tgz", + "integrity": "sha512-7mQlnZivFwrU6B3CswvmoNtVN8jqF9BcLf80uk7yh4fNA8PhFjAfQigi2Hu/Io0cmIvpOc7vn0/Rq3KtL5Ph8g==", "requires": { "async-lock": "^1.1.0", "clean-git-ref": "^2.0.1", @@ -4137,24 +14701,7 @@ "pify": "^4.0.1", "readable-stream": "^3.4.0", "sha.js": "^2.4.9", - "simple-get": "^3.0.2" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "simple-get": "^4.0.1" } }, "isstream": { @@ -4210,55 +14757,6 @@ "p-map": "^3.0.0", "rimraf": "^3.0.0", "uuid": "^3.3.3" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "istanbul-lib-report": { @@ -4270,6 +14768,23 @@ "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "istanbul-lib-source-maps": { @@ -4284,9 +14799,9 @@ } }, "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-0i77ZFLsb9U3DHi22WzmIngVzfoyxxbQcZRqlF3KoKmCJGq9nhFHoGi8FqBztN2rE8w6hURnZghetn0xpkVb6A==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -4294,15 +14809,66 @@ } }, "jest-diff": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", - "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.2.5.tgz", + "integrity": "sha512-7gfwwyYkeslOOVQY4tVq5TaQa92mWfC9COsVYMNVYyJTOYAqbIkoD3twi5A+h+tAPtAelRxkqY6/xu+jwTr0dA==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.1", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-docblock": { @@ -4315,140 +14881,155 @@ } }, "jest-get-type": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", - "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", + "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", "dev": true }, "jest-matcher-utils": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", - "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz", + "integrity": "sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.2.5.tgz", + "integrity": "sha512-ggXSLoPfIYcbmZ8glgEJZ8b+e0Msw/iddRmgkoO7lDAr9SmI65IIfv7VnvTnV4FGnIIUIjzM+fHRHO5RBvyAbQ==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", + "@jest/types": "^27.2.5", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", + "pretty-format": "^27.2.5", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "dependencies": { "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, "requires": { "@babel/highlight": "^7.14.5" } }, - "@babel/helper-validator-identifier": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", - "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "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" - } - } + "color-convert": "^2.0.1" } }, - "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==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "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==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } }, "jest-regex-util": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", - "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", + "version": "27.0.6", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", + "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", "dev": true }, "jju": { @@ -4464,13 +15045,18 @@ "dev": true }, "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + } } }, "jsbn": { @@ -4526,9 +15112,9 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "requires": { "minimist": "^1.2.5" } @@ -4560,13 +15146,13 @@ } }, "jsx-ast-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", - "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", + "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", "dev": true, "requires": { - "array-includes": "^3.1.1", - "object.assign": "^4.1.0" + "array-includes": "^3.1.3", + "object.assign": "^4.1.2" } }, "just-extend": { @@ -4576,10 +15162,11 @@ "dev": true }, "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.2.2.tgz", + "integrity": "sha512-uYS0vKTlBIjNCAUqrjlxmruxOEiZxZIHXyp32sdcGmP+ukFrmWUnE//RcPXJH3Vxrni1H2gsQbjHE0bH7MtMQQ==", "requires": { + "compress-brotli": "^1.3.6", "json-buffer": "3.0.1" } }, @@ -4595,6 +15182,16 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -4628,6 +15225,12 @@ "error-ex": "^1.2.0" } }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -4637,18 +15240,24 @@ } }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true }, "lodash.flattendeep": { "version": "4.4.0", @@ -4668,6 +15277,18 @@ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, "lodash.zip": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", @@ -4687,6 +15308,57 @@ "dev": true, "requires": { "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "loose-envify": { @@ -4704,12 +15376,13 @@ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { - "yallist": "^4.0.0" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "make-dir": { @@ -4758,14 +15431,6 @@ "requires": { "map-age-cleaner": "^0.1.3", "mimic-fn": "^3.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", - "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", - "dev": true - } } }, "merge2": { @@ -4775,28 +15440,34 @@ "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" } }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", + "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==" }, "mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", + "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", "requires": { - "mime-db": "1.45.0" + "mime-db": "1.50.0" } }, + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true + }, "mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", @@ -4824,33 +15495,55 @@ } }, "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" }, "dependencies": { "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + }, + "dependencies": { + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + } } }, "mocha": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", - "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -4886,39 +15579,49 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "ms": "2.1.2" + }, + "dependencies": { + "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 + } } }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "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-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "js-yaml": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", @@ -4928,39 +15631,12 @@ "argparse": "^2.0.1" } }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -4969,53 +15645,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true } } }, @@ -5037,9 +15666,9 @@ "dev": true }, "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" }, "nanoid": { "version": "3.1.20", @@ -5054,9 +15683,9 @@ "dev": true }, "needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -5093,48 +15722,42 @@ } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "requires": { + "whatwg-url": "^5.0.0" + } }, "node-gyp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-4.0.0.tgz", - "integrity": "sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", "requires": { - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^4.4.8", - "which": "1" + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { - "glob": "^7.1.3" + "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" } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" } } }, @@ -5155,12 +15778,47 @@ "tar": "^4" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "requires": { - "minimist": "^1.2.5" + "minipass": "^2.9.0" } }, "nopt": { @@ -5179,6 +15837,35 @@ "requires": { "glob": "^7.1.3" } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "requires": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" } } }, @@ -5191,10 +15878,16 @@ "process-on-spawn": "^1.0.0" } }, + "node-releases": { + "version": "1.1.77", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", + "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", + "dev": true + }, "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "requires": { "abbrev": "1" } @@ -5209,6 +15902,14 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "normalize-path": { @@ -5218,14 +15919,14 @@ "dev": true }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", "requires": { "npm-normalize-package-bin": "^1.0.1" } @@ -5294,6 +15995,163 @@ "spawn-wrap": "^2.0.0", "test-exclude": "^6.0.0", "yargs": "^15.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, "oauth-sign": { @@ -5307,9 +16165,9 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", "dev": true }, "object-keys": { @@ -5331,39 +16189,36 @@ } }, "object.entries": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", - "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" + "es-abstract": "^1.19.1" } }, "object.fromentries": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", - "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" + "es-abstract": "^1.19.1" } }, "object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" + "es-abstract": "^1.19.1" } }, "once": { @@ -5374,6 +16229,20 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -5417,9 +16286,9 @@ } }, "p-cancelable": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", - "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" }, "p-defer": { "version": "1.0.0", @@ -5441,21 +16310,21 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, "p-map": { @@ -5532,9 +16401,9 @@ } }, "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -5554,10 +16423,16 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-to-regexp": { @@ -5567,14 +16442,6 @@ "dev": true, "requires": { "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } } }, "path-type": { @@ -5588,25 +16455,81 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", "dev": true }, - "pify": { + "picomatch": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "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 + } } }, "please-upgrade-node": { @@ -5625,77 +16548,13 @@ "dev": true }, "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "dev": true, "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "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 - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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" - } - } + "picocolors": "^0.2.1", + "source-map": "^0.6.1" } }, "postcss-less": { @@ -5744,6 +16603,12 @@ "uniq": "^1.0.1" } }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", @@ -5840,12 +16705,52 @@ "tsutils": "^3.17.1" } }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "camelcase": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "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 + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -5858,12 +16763,40 @@ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, "get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + }, "globby": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", @@ -5886,12 +16819,49 @@ } } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", @@ -5900,17 +16870,43 @@ "requires": { "lru-cache": "^6.0.0" } + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.2.5.tgz", + "integrity": "sha512-+nYn2z9GgicO9JiqmY25Xtq8SYfZ/5VCpEU3pppHHNAhd1y+ZXxmNPd1evmNcAd6Hz4iBV2kf0UpGth5A/VJ7g==", "dev": true, "requires": { - "@jest/types": "^27.0.2", - "ansi-regex": "^5.0.0", + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" }, @@ -5923,11 +16919,6 @@ } } }, - "printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -5997,6 +16988,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "ramda": { "version": "0.25.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", @@ -6036,48 +17033,102 @@ "dev": true }, "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" }, "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "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 + } } }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "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" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, "readdirp": { @@ -6090,9 +17141,9 @@ } }, "regexp-tree": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.21.tgz", - "integrity": "sha512-kUUXjX4AnqnR8KRTCrayAo9PzYMRKmVoGgaz2tBuz0MF3g1ZbGebmtW0yFHfFK9CmBjQKeYIgoL22pFLBJY7sw==", + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", + "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", "dev": true }, "regexp-util": { @@ -6105,40 +17156,19 @@ } }, "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "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.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, "release-zalgo": { @@ -6213,22 +17243,6 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "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==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } } }, "require-directory": { @@ -6256,19 +17270,18 @@ "dev": true }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "dev": true, "requires": { - "is-core-module": "^2.1.0", "path-parse": "^1.0.6" } }, "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "responselike": { @@ -6291,19 +17304,46 @@ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + } } }, "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dev": true, + "requires": { + "regexp-tree": "~0.1.1" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -6315,9 +17355,27 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } }, "semver-compare": { "version": "1.0.0", @@ -6348,6 +17406,21 @@ "safe-buffer": "^5.0.1" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -6366,9 +17439,9 @@ "dev": true }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==" }, "simple-concat": { "version": "1.0.1", @@ -6376,29 +17449,34 @@ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "requires": { - "decompress-response": "^4.2.0", + "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" }, "dependencies": { "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { - "mimic-response": "^2.0.0" + "mimic-response": "^3.1.0" } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" } } }, "simple-html-tokenizer": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.10.tgz", - "integrity": "sha512-1DHMUmvUOGuUZ9/+cX/+hOhWhRD5dEw6lodn8WuV+T+cQ31hhBcCu1dcDsNotowi4mMaNhrLyKoS+DtB81HdDA==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.5.11.tgz", + "integrity": "sha512-C2WEK/Z3HoSFbYq8tI7ni3eOo/NneSPRoPpcM7WdLjFOArFuyXEjAoCdOC3DgMfRyziZQ1hCNR4mrNdWEvD0og==", "dev": true }, "sinon": { @@ -6413,6 +17491,29 @@ "diff": "^4.0.2", "nise": "^4.1.0", "supports-color": "^7.1.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "slash": { @@ -6430,6 +17531,38 @@ "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + } } }, "source-map": { @@ -6438,9 +17571,9 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6458,17 +17591,6 @@ "rimraf": "^3.0.0", "signal-exit": "^3.0.2", "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "spdx-correct": { @@ -6498,9 +17620,9 @@ } }, "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, "sprintf-js": { @@ -6532,9 +17654,9 @@ } }, "stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, "requires": { "escape-string-regexp": "^2.0.0" @@ -6554,6 +17676,21 @@ "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", "dev": true }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, "string-argv": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", @@ -6561,66 +17698,73 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "string.prototype.matchall": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", - "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz", + "integrity": "sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3" + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } }, "strip-bom": { @@ -6636,30 +17780,31 @@ "dev": true }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" } }, "table": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", - "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", + "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", "dev": true, "requires": { - "ajv": "^7.0.2", - "lodash": "^4.17.20", + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "dependencies": { "ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -6668,40 +17813,53 @@ "uri-js": "^4.2.2" } }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } } } }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "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" + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "dependencies": { "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -6716,13 +17874,10 @@ "tar-stream": "^1.1.2" }, "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "pump": { "version": "1.0.3", @@ -6747,6 +17902,35 @@ "readable-stream": "^2.3.0", "to-buffer": "^1.1.1", "xtend": "^4.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "test-exclude": { @@ -6758,6 +17942,22 @@ "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + } } }, "text-table": { @@ -6797,6 +17997,20 @@ "is-number": "^7.0.0" } }, + "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==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "transform-file": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/transform-file/-/transform-file-1.0.1.tgz", @@ -6825,23 +18039,43 @@ "dev": true }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz", + "integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==", "dev": true, "requires": { + "@cspotcode/source-map-support": "0.6.1", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", "yn": "3.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "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 + } } }, "tsconfig-paths": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", - "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", "dev": true, "requires": { "@types/json5": "^0.0.29", @@ -6874,17 +18108,17 @@ "dev": true }, "tslog": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.1.2.tgz", - "integrity": "sha512-sKhNPUMjf+POPxcWuGxinjilEjIzPCdehF/zIdp33ttv9ohIBWHMV9gpdGvJjWbZn09a5IqP1dmaYq56IPXZAg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.2.2.tgz", + "integrity": "sha512-8dwb1cYpj3/w/MZTrSkPrdlA44loUodGT8N6ULMojqV4YByVM7ynhvVs9JwcIYxhhHf4bz1C5O3NKIPehnGp/w==", "requires": { "source-map-support": "^0.5.19" } }, "tsutils": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.0.tgz", - "integrity": "sha512-A7BaLUPvcQ1cxVu72YfD+UMI3SQPTDv/w4ol6TOwLyI0hwfG9EC+cYlhdflJTmtYTgZ3KqdPSe/otxU4K3kArg==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "requires": { "tslib": "^1.8.1" @@ -6903,6 +18137,15 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -6910,9 +18153,9 @@ "dev": true }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, "typedarray-to-buffer": { @@ -6925,15 +18168,15 @@ } }, "typescript": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", - "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", + "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", "dev": true }, "uglify-js": { - "version": "3.12.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.4.tgz", - "integrity": "sha512-L5i5jg/SHkEqzN18gQMTWsZk3KelRsfD1wUVNqtq0kzqWQqcJjyL8yc1o8hJgRrWqrAl2mUFbhfznEIoi7zi2A==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.2.tgz", + "integrity": "sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A==", "dev": true, "optional": true }, @@ -6942,6 +18185,18 @@ "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==" }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "unherit": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", @@ -6978,14 +18233,6 @@ "is-plain-obj": "^2.0.0", "trough": "^1.0.0", "vfile": "^4.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true - } } }, "uniq": { @@ -7047,9 +18294,9 @@ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } @@ -7059,10 +18306,15 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "validate-npm-package-license": { @@ -7101,14 +18353,6 @@ "is-buffer": "^2.0.0", "unist-util-stringify-position": "^2.0.0", "vfile-message": "^2.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true - } } }, "vfile-location": { @@ -7138,72 +18382,49 @@ "tslib": "^1.9.3" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "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" - } - }, - "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 - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "leven": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", "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" - } } } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "requires": { "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -7216,35 +18437,6 @@ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "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=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "word-wrap": { @@ -7266,14 +18458,57 @@ "dev": true }, "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } } }, "wrappy": { @@ -7299,21 +18534,21 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yaml": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", - "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true }, "yaml-unist-parser": { @@ -7328,33 +18563,44 @@ } }, "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } } }, "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true }, "yargs-unparser": { "version": "2.0.0", diff --git a/package.json b/package.json index 716151d7..c91a863a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "git-documentdb", - "version": "0.4.0", + "version": "0.4.8", "description": "Offline-first database that syncs with Git", "main": "dist/main.js", "types": "dist/main.d.ts", @@ -9,20 +9,24 @@ }, "scripts": { "build": "rm -rf dist/* && npm run lint && tsc --project src/tsconfig.json", - "doc": "npm run build && npm run api-extractor && npm run crlf", - "mocha": "rm -rf test/database* && npx cross-env TS_NODE_FILES=true TS_NODE_PROJECT=tsconfig.mocha.json mocha", - "mocha-unit": "rm -rf test/database* && npx cross-env TS_NODE_FILES=true TS_NODE_PROJECT=tsconfig.mocha.json mocha --retries 0 --no-parallel", - "compile-tests": "tsc --project test/tsconfig.json && tsc --project test_intg/tsconfig.json", - "rm-test-db": "rm -rf test/database* test_intg/database*", - "test": "npm run rm-test-db && npx nyc npm run mocha \"test/**/*.test.ts\" \"test_intg/**/*.test.ts\" && npm run rm-test-db", - "test-noretry": "npm run rm-test-db && npx nyc npm run mocha-noretry \"test/**/*.test.ts\" \"test_intg/**/*.test.ts\" && npm run rm-test-db", - "test-serial": "npm run rm-test-db && npx nyc npm run mocha-serial \"test/**/*.test.ts\" \"test_intg/**/*.test.ts\" && npm run rm-test-db", + "doc": "npm run build && rm -rf docs-api/* && npm run api-extractor && npm run crlf", + "mocha-parallel": "npm run rm-test-db && npx cross-env TS_NODE_FILES=true TS_NODE_PROJECT=tsconfig.mocha.json mocha", + "mocha-no-parallel": "npm run rm-test-db && npx cross-env TS_NODE_FILES=true TS_NODE_PROJECT=tsconfig.mocha.json mocha --retries 0 --no-parallel", + "mocha-unit-parallel": "npm run rm-test-db && npx cross-env TS_NODE_FILES=true TS_NODE_PROJECT=tsconfig.mocha.json mocha --retries 0", + "mocha-unit": "npm run rm-test-db && npx cross-env TS_NODE_FILES=true TS_NODE_PROJECT=tsconfig.mocha.json mocha --retries 0 --no-parallel", + "compile-tests": "tsc --project test/tsconfig.json && tsc --project test_plugin/tsconfig.json ", + "rm-test-db": "rm -rf test/database* test_plugin/database*", + "bench": "rm -rf benchmark/database* && npx ts-node ", + "test": "npx nyc npm run mocha-parallel \"test/**/*.test.ts\" && npm run rm-test-db", + "test-plugin": "npm run mocha-parallel \"test_plugin/**/*.test.ts\" && npm run rm-test-db", "upload-coverage": "npx coveralls < coverage/lcov.info", "prepare": "", "prepublishOnly": "npm run build && npm test", "api-extractor": "api-extractor run --local --verbose && npx api-documenter markdown -i ./temp -o ./docs-api", "lint": "eslint --fix --ext .ts .", - "crlf": "npx crlf --set=LF docs-api/* etc/* " + "crlf": "npx crlf --set=LF docs-api/* etc/* ", + "remove-remote": "node --experimental-modules --experimental-json-modules remove_remote_repositories.mjs", + "clear": "npx rimraf node_modules" }, "repository": { "type": "git", @@ -40,13 +44,14 @@ "bugs": { "url": "https://github.com/sosuisen/git-documentdb/issues" }, - "homepage": "https://github.com/sosuisen/git-documentdb#readme", + "homepage": "https://gitddb.com/", "devDependencies": { "@microsoft/api-extractor": "^7.16.0", "@octokit/types": "^6.12.2", - "@sosuisen/api-documenter": "^7.13.25", - "@types/expect": "^24.3.0", - "@types/fs-extra": "^9.0.6", + "@sosuisen/api-documenter": "^7.13.27", + "@types/async-lock": "^1.1.2", + "@types/fs-extra": "^9.0.12", + "@types/js-yaml": "^4.0.3", "@types/mocha": "^8.2.2", "@types/node": "^14.14.20", "@types/parse-git-config": "^3.0.0", @@ -60,24 +65,27 @@ "eslint": "^7.17.0", "eslint-config-standardize": "^0.7.1", "eslint-plugin-prettierx": "^0.14.0", + "eslint-plugin-unicorn": "^36.0.0", "expect": "^27.0.2", + "hmtid": "^0.1.0", "mocha": "^8.3.2", "nyc": "^15.1.0", "parse-git-config": "^3.0.0", "sinon": "^10.0.0", - "ts-node": "^9.1.1", + "ts-node": "^10.1.0", "tsconfig-paths": "^3.9.0", "typescript": "^4.3.4" }, "dependencies": { "@octokit/rest": "^18.3.5", "@sosuisen/jsondiffpatch": "^0.4.7", - "@sosuisen/nodegit": "^0.27.3", - "@types/async-lock": "^1.1.2", "async-lock": "^1.3.0", "cross-blob": "^2.0.0", "fs-extra": "^9.1.0", - "isomorphic-git": "^1.8.2", + "git-documentdb-plugin-remote-nodegit": "^1.0.4", + "git-documentdb-remote-errors": "^1.0.3", + "isomorphic-git": "^1.23.0", + "js-yaml": "^4.1.0", "ot-json1": "^1.0.2", "rimraf": "^3.0.2", "tslog": "^3.1.2", diff --git a/remove_remote_repositories.mjs b/remove_remote_repositories.mjs new file mode 100644 index 00000000..c9470555 --- /dev/null +++ b/remove_remote_repositories.mjs @@ -0,0 +1,48 @@ +import { Octokit } from '@octokit/rest'; + +const reposPrefix = 'test_'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN; + +const octokit = new Octokit({ + auth: token, +}); + +const len = 0; +const promises = []; + +const removeRemoteRepositories = async () => { + // eslint-disable-next-line no-await-in-loop + const reposArray = await octokit.paginate( + octokit.repos.listForAuthenticatedUser, + { per_page: 100 }, + response => + response.data.filter(repos => { + if (repos) { + const urlArray = repos.full_name.split('/'); + const repo = urlArray[1]; + return repo.startsWith(reposPrefix); + } + return false; + }) + ); + // console.log(` - Got ${reposArray.length} repositories`); + reposArray.forEach(repos => { + const urlArray = repos.full_name.split('/'); + const owner = urlArray[0]; + const repo = urlArray[1]; + promises.push( + octokit.repos.delete({ owner, repo }).catch(err => { + if (err.status !== 404) { + console.debug(err); + } + }) + ); + }); + console.log(` - Start to remove repositories..`); + // eslint-disable-next-line no-await-in-loop + await Promise.all(promises); + console.log(` - Done.`); +}; + +removeRemoteRepositories(); \ No newline at end of file diff --git a/src/collection.ts b/src/collection.ts index 287eb4a4..a1a14d51 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -8,6 +8,7 @@ import fs from 'fs'; +import path from 'path'; import { readTree, resolveRef } from 'isomorphic-git'; import { monotonicFactory, ULID } from 'ulid'; import { Err } from './error'; @@ -36,9 +37,8 @@ import { } from './types'; import { GitDDBInterface } from './types_gitddb'; import { Validator } from './validator'; -import { toSortedJSONString } from './utils'; -import { GIT_DOCUMENTDB_METADATA_DIR, JSON_EXT } from './const'; -import { getImpl } from './crud/get'; +import { GIT_DOCUMENTDB_METADATA_DIR } from './const'; +import { getImpl, getJsonDocFromWorkingDir } from './crud/get'; import { getHistoryImpl } from './crud/history'; import { deleteImpl } from './crud/delete'; import { findImpl } from './crud/find'; @@ -52,7 +52,7 @@ import { ICollection } from './types_collection'; * @remarks * In a collection API, shortId (shortName) is used instead of _id (name). * - * - shortId is a file path whose collectionPath and .json extension are omitted. (_id = collectionPath + shortId) + * - shortId is a file path whose collectionPath and extension are omitted. (_id = collectionPath + shortId) * * - shortName is a file path whose collectionPath is omitted. (name = collectionPath + shortName) * @@ -109,6 +109,7 @@ export class Collection implements ICollection { * * @remarks * Child collection inherits Parent's CollectionOptions. + * * @public */ get parent (): ICollection | undefined { @@ -120,6 +121,7 @@ export class Collection implements ICollection { * * @param collectionPathFromParent - A relative collectionPath from a parent collection. * @param parent - A parent collection of this collection. + * * @throws {@link Err.InvalidCollectionPathCharacterError} * @throws {@link Err.InvalidCollectionPathLengthError} * @@ -134,19 +136,26 @@ export class Collection implements ICollection { this._gitDDB = gitDDB; this._collectionPath = Validator.normalizeCollectionPath(collectionPathFromParent); this._gitDDB.validator.validateCollectionPath(this.collectionPath); - this._monoID = monotonicFactory(); if (parent === undefined) { this._parent = undefined; options ??= { namePrefix: '', + debounceTime: undefined, }; + options.debounceTime ??= -1; } else { this._parent = parent; } - this._options = { ...parent?.options!, ...options }; + + if (this._options.idGenerator !== undefined) { + this._monoID = this._options.idGenerator; + } + else { + this._monoID = monotonicFactory(); + } } /*********************************************** @@ -163,8 +172,11 @@ export class Collection implements ICollection { * * @public */ - generateId () { - return this._options.namePrefix + this._monoID(Date.now()); + generateId (seedTime?: number) { + if (seedTime === undefined) { + seedTime = Date.now(); + } + return this._options.namePrefix + this._monoID(seedTime); } /** @@ -188,14 +200,10 @@ export class Collection implements ICollection { * * @param dirPath - dirPath is a relative path from collectionPath. Default is ''. * @returns Array of Collections which does not include ''. - * @throws {@link Err.RepositoryNotOpenError} * * @public */ async getCollections (dirPath = ''): Promise { - if (!this._gitDDB.isOpened) { - throw new Err.RepositoryNotOpenError(); - } dirPath = Validator.normalizeCollectionPath(this.collectionPath + dirPath); dirPath = dirPath.slice(0, -1); @@ -230,25 +238,27 @@ export class Collection implements ICollection { /** * Insert a JSON document if not exists. Otherwise, update it. * - * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. + * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and extension are omitted. * * @remarks - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}${jsonDoc._id}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}${jsonDoc._id}${extension}`. * * - If _id is undefined, it is automatically generated. * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * * @public */ @@ -257,10 +267,10 @@ export class Collection implements ICollection { /** * Insert a JSON document if not exists. Otherwise, update it. * - * @param shortId - shortId is a file path whose collectionPath and .json extension are omitted. + * @param shortId - shortId is a file path whose collectionPath and extension are omitted. * * @remarks - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}${extension}`. * * - If shortId is undefined, it is automatically generated. * @@ -270,17 +280,18 @@ export class Collection implements ICollection { * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) - * @throws {@link Err.InvalidCollectionPathCharacterError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * * @public */ @@ -309,7 +320,6 @@ export class Collection implements ICollection { ): Promise { let shortId: string; let _id: string; - let shortName: string; let jsonDoc: JsonDoc; // Resolve overloads @@ -321,14 +331,12 @@ export class Collection implements ICollection { if (!shortIdOrDoc) shortIdOrDoc = this.generateId(); shortId = shortIdOrDoc; _id = this.collectionPath + shortId; - shortName = shortId + JSON_EXT; jsonDoc = jsonDocOrOptions as JsonDoc; } else { if (!shortIdOrDoc._id) shortIdOrDoc._id = this.generateId(); shortId = shortIdOrDoc._id; _id = this.collectionPath + shortId; - shortName = shortId + JSON_EXT; jsonDoc = shortIdOrDoc as JsonDoc; options = jsonDocOrOptions as PutOptions; } @@ -341,7 +349,8 @@ export class Collection implements ICollection { return Promise.reject(new Err.InvalidJsonObjectError(shortId)); } clone._id = _id; - const data = toSortedJSONString(clone); + const { extension, data } = this._gitDDB.serializeFormat.serialize(clone); + const shortName = shortId + extension; try { this._gitDDB.validator.validateId(shortId); this._gitDDB.validator.validateDocument(clone); @@ -349,6 +358,11 @@ export class Collection implements ICollection { return Promise.reject(err); } + options ??= { + debounceTime: undefined, + }; + options.debounceTime ??= this._options.debounceTime; + return putImpl( this._gitDDB, this.collectionPath, @@ -370,31 +384,35 @@ export class Collection implements ICollection { /** * Insert a JSON document * - * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. + * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and extension are omitted. * * @remarks * - Throws SameIdExistsError when a document that has the same _id exists. It might be better to use put() instead of insert(). * * - If _id is undefined, it is automatically generated. * - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}${extension}`. + * + * @param jsonDoc - See {@link JsonDoc} for restriction. * * @param jsonDoc - See {@link JsonDoc} for restriction. * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.SameIdExistsError} (from putWorker) + * @throws - {@link Err.SameIdExistsError} * * @public */ @@ -403,12 +421,12 @@ export class Collection implements ICollection { /** * Insert a JSON document * - * @param shortId - shortId is a file path whose collectionPath and .json extension are omitted. + * @param shortId - shortId is a file path whose collectionPath and extension are omitted. * * @remarks * - Throws SameIdExistsError when a document that has the same _id exists. It might be better to use put() instead of insert(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}${extension}`. * * - If shortId is undefined, it is automatically generated. * @@ -416,18 +434,20 @@ export class Collection implements ICollection { * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.SameIdExistsError} (from putWorker) + * @throws - {@link Err.SameIdExistsError} * * @public */ @@ -457,12 +477,18 @@ export class Collection implements ICollection { shortIdOrDoc === undefined || shortIdOrDoc === null ) { - options ??= {}; + options ??= { + debounceTime: undefined, + }; options.insertOrUpdate = 'insert'; + options.debounceTime ??= this._options.debounceTime; } else { - jsonDocOrOptions ??= {}; + jsonDocOrOptions ??= { + debounceTime: undefined, + }; (jsonDocOrOptions as PutOptions).insertOrUpdate = 'insert'; + (jsonDocOrOptions as PutOptions).debounceTime ??= this._options.debounceTime; } return this.put(shortIdOrDoc, jsonDocOrOptions, options); @@ -471,12 +497,12 @@ export class Collection implements ICollection { /** * Update a JSON document * - * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. + * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and extension are omitted. * * @remarks * - Throws DocumentNotFoundError if a specified document does not exist. It might be better to use put() instead of update(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${jsonDoc._id}${extension}`. * * - If _id is undefined, it is automatically generated. * @@ -484,18 +510,20 @@ export class Collection implements ICollection { * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.DocumentNotFoundError} + * @throws - {@link Err.DocumentNotFoundError} * * @public */ @@ -504,29 +532,31 @@ export class Collection implements ICollection { /** * Update a JSON document * - * @param shortId - shortId is a file path whose collectionPath and .json extension are omitted. + * @param shortId - shortId is a file path whose collectionPath and extension are omitted. * * @remarks * - Throws DocumentNotFoundError if a specified data does not exist. It might be better to use put() instead of update(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortId}${extension}`. * * - An update operation is not skipped even if no change occurred on a specified data. * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.DocumentNotFoundError} + * @throws - {@link Err.DocumentNotFoundError} * * @public */ @@ -556,12 +586,18 @@ export class Collection implements ICollection { shortIdOrDoc === undefined || shortIdOrDoc === null ) { - options ??= {}; + options ??= { + debounceTime: undefined, + }; options.insertOrUpdate = 'update'; + options.debounceTime ??= this._options.debounceTime; } else { - jsonDocOrOptions ??= {}; + jsonDocOrOptions ??= { + debounceTime: undefined, + }; (jsonDocOrOptions as PutOptions).insertOrUpdate = 'update'; + (jsonDocOrOptions as PutOptions).debounceTime ??= this._options.debounceTime; } return this.put(shortIdOrDoc, jsonDocOrOptions, options); @@ -570,30 +606,32 @@ export class Collection implements ICollection { /** * Insert data if not exists. Otherwise, update it. * - * @param shortName - shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with .json extension. + * @param shortName - shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with extension. * * @remarks - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}${extension}`. * * - If shortName is undefined, it is automatically generated. * - * - _id property of a JsonDoc is automatically set or overwritten by shortName parameter whose .json extension is omitted. + * - _id property of a JsonDoc is automatically set or overwritten by shortName parameter whose extension is omitted. * * - An update operation is not skipped even if no change occurred on a specified data. * * @throws {@link Err.InvalidJsonFileExtensionError} * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * * @public */ @@ -619,13 +657,14 @@ export class Collection implements ICollection { data = doc; } else if (typeof doc === 'object') { - if (!shortName) shortName = this.generateId() + JSON_EXT; + const extension = this._gitDDB.serializeFormat.extension(doc); + if (!shortName) shortName = this.generateId() + extension; docType = 'json'; // JsonDoc - if (!shortName.endsWith(JSON_EXT)) { + if (!shortName.endsWith(extension)) { return Promise.reject(new Err.InvalidJsonFileExtensionError()); } - shortId = shortName.replace(new RegExp(JSON_EXT + '$'), ''); + shortId = shortName.replace(new RegExp(extension + '$'), ''); // Validate JSON let clone; @@ -635,7 +674,8 @@ export class Collection implements ICollection { return Promise.reject(new Err.InvalidJsonObjectError(shortId)); } clone._id = this.collectionPath + shortId; - data = toSortedJSONString(clone); + data = this._gitDDB.serializeFormat.serialize(clone).data; + try { this._gitDDB.validator.validateDocument(clone); } catch (err) { @@ -652,6 +692,11 @@ export class Collection implements ICollection { return Promise.reject(err); } + options ??= { + debounceTime: undefined, + }; + options.debounceTime ??= this._options.debounceTime; + return putImpl( this._gitDDB, this.collectionPath, @@ -689,31 +734,33 @@ export class Collection implements ICollection { /** * Insert a data * - * @param shortName - shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with .json extension. + * @param shortName - shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with extension. * * @remarks * - Throws SameIdExistsError when data that has the same _id exists. It might be better to use put() instead of insert(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}${extension}`. * * - If shortName is undefined, it is automatically generated. * - * - _id property of a JsonDoc is automatically set or overwritten by shortName parameter whose .json extension is omitted. + * - _id property of a JsonDoc is automatically set or overwritten by shortName parameter whose extension is omitted. * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.SameIdExistsError} (from putWorker) + * @throws - {@link Err.SameIdExistsError} * * @public */ @@ -723,8 +770,11 @@ export class Collection implements ICollection { options?: PutOptions ): Promise { // Resolve overloads - options ??= {}; + options ??= { + debounceTime: undefined, + }; options.insertOrUpdate = 'insert'; + options.debounceTime ??= this._options.debounceTime; return this.putFatDoc(shortName, doc, options); } @@ -732,31 +782,33 @@ export class Collection implements ICollection { /** * Update a data * - * @param shortName - shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with .json extension. + * @param shortName - shortName is a file path whose collectionPath is omitted. shortName of JsonDoc must ends with extension. * * @remarks * - Throws DocumentNotFoundError if a specified data does not exist. It might be better to use put() instead of update(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${Collection#collectionPath}/${shortName}${extension}`. * - * - _id property of a JsonDoc is automatically set or overwritten by shortName parameter whose .json extension is omitted. + * - _id property of a JsonDoc is automatically set or overwritten by shortName parameter whose extension is omitted. * * - An update operation is not skipped even if no change occurred on a specified data. * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.DocumentNotFoundError} + * @throws - {@link Err.DocumentNotFoundError} * * @public */ @@ -766,8 +818,11 @@ export class Collection implements ICollection { options?: PutOptions ): Promise { // Resolve overloads - options ??= {}; + options ??= { + debounceTime: undefined, + }; options.insertOrUpdate = 'update'; + options.debounceTime ??= this._options.debounceTime; return this.putFatDoc(shortName, doc, options); } @@ -775,7 +830,7 @@ export class Collection implements ICollection { /** * Get a JSON document * - * @param shortId - shortId is a file path whose collectionPath and .json extension are omitted. + * @param shortId - shortId is a file path whose collectionPath and extension are omitted. * * @returns * - undefined if a specified document does not exist. @@ -783,16 +838,31 @@ export class Collection implements ICollection { * - JsonDoc may not have _id property when an app other than GitDocumentDB creates it. * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public */ - get (_id: string): Promise { - const shortName = _id + JSON_EXT; - return getImpl(this._gitDDB, shortName, this.collectionPath, { - forceDocType: 'json', - }) as Promise; + async get (_id: string): Promise { + let shortName = _id + this._gitDDB.serializeFormat.firstExtension; + const result = (await getJsonDocFromWorkingDir( + this._gitDDB, + shortName, + this.collectionPath, + this._gitDDB.serializeFormat + )) as Promise; + if ( + result === undefined && + this._gitDDB.serializeFormat.secondExtension !== undefined + ) { + shortName = _id + this._gitDDB.serializeFormat.secondExtension; + return getJsonDocFromWorkingDir( + this._gitDDB, + shortName, + this.collectionPath, + this._gitDDB.serializeFormat + ) as Promise; + } + return result; } /** @@ -803,22 +873,47 @@ export class Collection implements ICollection { * @returns * - undefined if a specified data does not exist. * - * - FatJsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. + * - FatJsonDoc if the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. * * - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. * * - getOptions.forceDocType always overwrite return type. * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public */ - getFatDoc (shortName: string, getOptions?: GetOptions): Promise { - return getImpl(this._gitDDB, shortName, this.collectionPath, getOptions, { - withMetadata: true, - }) as Promise; + async getFatDoc ( + shortName: string, + getOptions?: GetOptions + ): Promise { + const result = (await getImpl( + this._gitDDB, + shortName, + this.collectionPath, + this._gitDDB.serializeFormat, + getOptions, + { + withMetadata: true, + } + )) as Promise; + if ( + result === undefined && + this._gitDDB.serializeFormat.secondExtension !== undefined + ) { + return getImpl( + this._gitDDB, + shortName, + this.collectionPath, + this._gitDDB.serializeFormat, + getOptions, + { + withMetadata: true, + } + ) as Promise; + } + return result; } /** @@ -830,16 +925,16 @@ export class Collection implements ICollection { * - undefined if a specified oid does not exist. * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public */ - getDocByOid (fileOid: string, docType: DocType = 'binary'): Promise { + getDocByOid (fileOid: string, docType: DocType = 'text'): Promise { return getImpl( this._gitDDB, '', this.collectionPath, + this._gitDDB.serializeFormat, { forceDocType: docType }, { withMetadata: false, @@ -851,7 +946,7 @@ export class Collection implements ICollection { /** * Get an old revision of a JSON document * - * @param shortId - shortId is a file path whose collectionPath and .json extension are omitted. + * @param shortId - shortId is a file path whose collectionPath and extension are omitted. * @param revision - Specify a number to go back to old revision. Default is 0. * See {@link git-documentdb#Collection.getHistory} for the array of revisions. * @param historyOptions - The array of revisions is filtered by HistoryOptions.filter. @@ -859,6 +954,8 @@ export class Collection implements ICollection { * @remarks * - undefined if a specified document does not exist or it is deleted. * + * - If serializeFormat is front-matter, this function can't correctly distinguish files that has the same _id but different extension. Use getFatDocOldRevision() instead. e.g.) foo.md and foo.yml + * * @example * ``` * collection.getOldRevision(_shortId, 0); // returns the latest document. @@ -866,28 +963,44 @@ export class Collection implements ICollection { * ``` * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public */ - getOldRevision ( + async getOldRevision ( shortId: string, revision: number, historyOptions?: HistoryOptions ): Promise { - const shortName = shortId + JSON_EXT; - return getImpl( + let shortName = shortId + this._gitDDB.serializeFormat.firstExtension; + const result = (await getImpl( this._gitDDB, shortName, this.collectionPath, + this._gitDDB.serializeFormat, { forceDocType: 'json' }, { withMetadata: false, revision: revision, }, historyOptions - ) as Promise; + )) as Promise; + if (result === undefined && this._gitDDB.serializeFormat !== undefined) { + shortName = shortId + this._gitDDB.serializeFormat.secondExtension; + return getImpl( + this._gitDDB, + shortName, + this.collectionPath, + this._gitDDB.serializeFormat, + { forceDocType: 'json' }, + { + withMetadata: false, + revision: revision, + }, + historyOptions + ) as Promise; + } + return result; } /** @@ -901,7 +1014,7 @@ export class Collection implements ICollection { * @remarks * - undefined if a specified data does not exist or it is deleted. * - * - JsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. + * - JsonDoc if the file extension is SerializedFormat.extension. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. * * - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. * @@ -914,7 +1027,6 @@ export class Collection implements ICollection { * ``` * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -929,6 +1041,7 @@ export class Collection implements ICollection { this._gitDDB, shortName, this.collectionPath, + this._gitDDB.serializeFormat, getOptions, { withMetadata: true, @@ -944,11 +1057,12 @@ export class Collection implements ICollection { * @remarks * - By default, revisions are sorted by reverse chronological order. However, keep in mind that Git dates may not be consistent across repositories. * - * @param shortId - shortId is a file path whose collectionPath and .json extension is omitted. + * - If serializeFormat is front-matter, this function can't work for .yml files. Use getFatDocHistory() instead. e.g.) foo.yml + * + * @param shortId - shortId is a file path whose collectionPath and extension is omitted. * @param historyOptions - The array of revisions is filtered by HistoryOptions.filter. * - * @returns Array of JsonDoc or undefined. - * - undefined if a specified document does not exist or it is deleted. + * @returns Array of JsonDoc or undefined if a specified document does not exist or it is deleted. * * @example * ``` @@ -980,7 +1094,6 @@ export class Collection implements ICollection { * ``` * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -989,11 +1102,12 @@ export class Collection implements ICollection { _id: string, historyOptions?: HistoryOptions ): Promise<(JsonDoc | undefined)[]> { - const shortName = _id + JSON_EXT; + const shortName = _id + this._gitDDB.serializeFormat.firstExtension; return getHistoryImpl( this._gitDDB, shortName, this.collectionPath, + this._gitDDB.serializeFormat, historyOptions, { forceDocType: 'json' }, false @@ -1011,14 +1125,13 @@ export class Collection implements ICollection { * @returns Array of FatDoc or undefined. * - undefined if a specified data does not exist or it is deleted. * - * - Array of FatJsonDoc if isJsonDocCollection is true or the file extension is '.json'. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. + * - Array of FatJsonDoc if isJsonDocCollection is true or the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. * * - Array of FatBinaryDoc if described in .gitattribtues, otherwise array of FatTextDoc. * * - getOptions.forceDocType always overwrite return type. * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1032,6 +1145,7 @@ export class Collection implements ICollection { this._gitDDB, shortName, this.collectionPath, + this._gitDDB.serializeFormat, historyOptions, getOptions, true @@ -1041,16 +1155,18 @@ export class Collection implements ICollection { /** * Delete a JSON document * - * @param shortId - shortId is a file path whose collectionPath and .json extension is omitted. + * @param shortId - shortId is a file path whose collectionPath and extension is omitted. * * @throws {@link Err.UndefinedDocumentIdError} - * @throws {@link Err.DatabaseClosingError} (from deleteImpl) - * @throws {@link Err.TaskCancelError} (from deleteImpl) * - * @throws {@link Err.RepositoryNotOpenError} (from deleteWorker) - * @throws {@link Err.UndefinedDBError} (from deleteWorker) - * @throws {@link Err.DocumentNotFoundError} (from deleteWorker) - * @throws {@link Err.CannotDeleteDataError} (from deleteWorker) + * @privateRemarks # Errors from deleteImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} + * + * @throws # Errors from deleteWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotDeleteDataError} * * @public */ @@ -1059,16 +1175,18 @@ export class Collection implements ICollection { /** * Delete a document by _id property in JsonDoc * - * @param jsonDoc - JsonDoc whose _id is shortId. Only the _id property is referenced. shortId is a file path whose collectionPath and .json extension are omitted. + * @param jsonDoc - JsonDoc whose _id is shortId. Only the _id property is referenced. shortId is a file path whose collectionPath and extension are omitted. * * @throws {@link Err.UndefinedDocumentIdError} - * @throws {@link Err.DatabaseClosingError} (from deleteImpl) - * @throws {@link Err.TaskCancelError} (from deleteImpl) * - * @throws {@link Err.RepositoryNotOpenError} (from deleteWorker) - * @throws {@link Err.UndefinedDBError} (from deleteWorker) - * @throws {@link Err.DocumentNotFoundError} (from deleteWorker) - * @throws {@link Err.CannotDeleteDataError} (from deleteWorker) + * @privateRemarks # Errors from deleteImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} + * + * @throws # Errors from deleteWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotDeleteDataError} * * @public */ @@ -1082,7 +1200,7 @@ export class Collection implements ICollection { options?: DeleteOptions ): Promise; - delete ( + async delete ( shortIdOrDoc: string | JsonDoc, options?: DeleteOptions ): Promise { @@ -1096,18 +1214,31 @@ export class Collection implements ICollection { else { return Promise.reject(new Err.UndefinedDocumentIdError()); } - const shortName = shortId + JSON_EXT; - - return deleteImpl(this._gitDDB, this.collectionPath, shortId, shortName, options).then( - res => { - const deleteResult: PutResultJsonDoc = { - ...res, - _id: shortId, - type: 'json', - }; - return deleteResult; + let shortName = shortId + this._gitDDB.serializeFormat.firstExtension; + + // Check if file exists for deleting FrontMatter + if (this._gitDDB.serializeFormat.secondExtension !== undefined) { + const fullDocPath = this.collectionPath + shortName; + const filePath = path.resolve(this._gitDDB.workingDir, fullDocPath); + if (!fs.existsSync(filePath)) { + shortName = shortId + this._gitDDB.serializeFormat.secondExtension; } - ); + } + + return await deleteImpl( + this._gitDDB, + this.collectionPath, + shortId, + shortName, + options + ).then(res => { + const deleteResult: PutResultJsonDoc = { + ...res, + _id: shortId, + type: 'json', + }; + return deleteResult; + }); } /** @@ -1116,13 +1247,15 @@ export class Collection implements ICollection { * @param shortName - shortName is a file path whose collectionPath is omitted. * * @throws {@link Err.UndefinedDocumentIdError} - * @throws {@link Err.DatabaseClosingError} (from deleteImpl) - * @throws {@link Err.TaskCancelError} (from deleteImpl) * - * @throws {@link Err.RepositoryNotOpenError} (from deleteWorker) - * @throws {@link Err.UndefinedDBError} (from deleteWorker) - * @throws {@link Err.DocumentNotFoundError} (from deleteWorker) - * @throws {@link Err.CannotDeleteDataError} (from deleteWorker) + * @privateRemarks # Errors from deleteImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} + * + * @throws # Errors from deleteWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotDeleteDataError} * * @public */ @@ -1131,15 +1264,17 @@ export class Collection implements ICollection { return Promise.reject(new Err.UndefinedDocumentIdError()); } - const docType: DocType = shortName.endsWith('.json') ? 'json' : 'text'; + const docType: DocType = this._gitDDB.serializeFormat.hasObjectExtension(shortName) + ? 'json' + : 'text'; if (docType === 'text') { // TODO: select binary or text by .gitattribtues } - const shortId = shortName.replace(new RegExp(JSON_EXT + '$'), ''); + const shortId = this._gitDDB.serializeFormat.removeExtension(shortName); return deleteImpl(this._gitDDB, this.collectionPath, shortId, shortName, options).then( res => { - // NOTE: Cannot detect JsonDoc whose file path does not end with '.json' + // NOTE: Cannot detect JsonDoc whose file path does not end with SerializeFormat.extension if (docType === 'json') { const deleteResult: DeleteResultJsonDoc = { ...res, @@ -1172,7 +1307,6 @@ export class Collection implements ICollection { * Get all the JSON documents * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1180,24 +1314,33 @@ export class Collection implements ICollection { find (options?: FindOptions): Promise { options ??= {}; options.forceDocType ??= 'json'; - return findImpl(this._gitDDB, this.collectionPath, true, false, options) as Promise< - JsonDoc[] - >; + return findImpl( + this._gitDDB, + this.collectionPath, + this._gitDDB.serializeFormat, + true, + false, + options + ) as Promise; } /** * Get all the FatDoc data * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public */ findFatDoc (options?: FindOptions): Promise { - return findImpl(this._gitDDB, this.collectionPath, false, true, options) as Promise< - FatDoc[] - >; + return findImpl( + this._gitDDB, + this.collectionPath, + this._gitDDB.serializeFormat, + false, + true, + options + ) as Promise; } /*********************************************** diff --git a/src/const.ts b/src/const.ts index ac0b2e17..0975644e 100644 --- a/src/const.ts +++ b/src/const.ts @@ -42,15 +42,15 @@ export const DUPLICATED_FILE_POSTFIX = '-from-'; /** * @public */ -export const FILE_REMOVE_TIMEOUT = 7000; +export const FILE_CREATE_TIMEOUT = 2000; /** * @public */ -export const FIRST_COMMIT_MESSAGE = 'first commit'; +export const FILE_REMOVE_TIMEOUT = 7000; /** * @public */ -export const GIT_DOCUMENTDB_APP_INFO_ID = '.gitddb/app'; +export const FIRST_COMMIT_MESSAGE = 'first commit'; /** * @public */ @@ -62,7 +62,15 @@ export const GIT_DOCUMENTDB_METADATA_DIR = '.gitddb'; /** * @public */ -export const JSON_EXT = '.json'; +export const JSON_POSTFIX = '.json'; +/** + * @public + */ +export const FRONT_MATTER_POSTFIX = '.md'; +/** + * @public + */ +export const YAML_POSTFIX = '.yml'; /** * @public */ diff --git a/src/crud/blob.ts b/src/crud/blob.ts index 16f452cf..7b40bbb9 100644 --- a/src/crud/blob.ts +++ b/src/crud/blob.ts @@ -7,11 +7,124 @@ */ import fs from 'fs'; +import yaml from 'js-yaml'; import { readBlob, ReadBlobResult, resolveRef } from 'isomorphic-git'; -import { JSON_EXT } from '../const'; +import { FRONT_MATTER_POSTFIX, YAML_POSTFIX } from '../const'; import { utf8decode } from '../utils'; import { Err } from '../error'; -import { FatBinaryDoc, FatJsonDoc, FatTextDoc, JsonDoc } from '../types'; +import { + FatBinaryDoc, + FatDoc, + FatJsonDoc, + FatTextDoc, + JsonDoc, + SerializeFormat, +} from '../types'; + +/** + * textToJsonDoc + * @throws {@link Err.InvalidJsonObjectError} + */ +// eslint-disable-next-line complexity +export function textToJsonDoc ( + text: string, + serializeFormat: SerializeFormat, + extension: string, + shortId?: string +): JsonDoc { + let jsonDoc: JsonDoc; + if (serializeFormat.format === 'front-matter') { + if (extension === YAML_POSTFIX) { + try { + jsonDoc = yaml.load(text) as JsonDoc; + } catch { + throw new Err.InvalidJsonObjectError(shortId); + } + if (jsonDoc === undefined) { + if (shortId !== undefined) { + jsonDoc = { + _id: shortId, + }; + } + else { + jsonDoc = {}; + } + } + } + else { + const mdArray = text.split('\n'); + let yamlText = ''; + let markdownText = ''; + let startFrontMatter = false; + let endFrontMatter = false; + for (let i = 0; i < mdArray.length; i++) { + if (mdArray[i] === '---') { + // eslint-disable-next-line max-depth + if (!startFrontMatter) { + startFrontMatter = true; + continue; + } + else if (!endFrontMatter) { + endFrontMatter = true; + continue; + } + } + if (startFrontMatter && !endFrontMatter) { + if (yamlText !== '') { + yamlText += '\n'; + } + yamlText += mdArray[i]; + } + else if (endFrontMatter) { + if (markdownText !== '') { + markdownText += '\n'; + } + markdownText += mdArray[i]; + } + } + + if (!endFrontMatter) { + markdownText = text; + if (shortId !== undefined) { + jsonDoc = { + _id: shortId, + }; + } + else { + jsonDoc = {}; + } + } + else { + try { + jsonDoc = yaml.load(yamlText) as JsonDoc; + } catch { + throw new Err.InvalidJsonObjectError(shortId); + } + if (jsonDoc === undefined) { + if (shortId !== undefined) { + jsonDoc = { + _id: shortId, + }; + } + else { + jsonDoc = {}; + } + } + } + if (markdownText !== '' || extension === FRONT_MATTER_POSTFIX) { + jsonDoc._body = markdownText; + } + } + } + else { + try { + jsonDoc = (JSON.parse(text) as unknown) as JsonDoc; + } catch { + throw new Err.InvalidJsonObjectError(shortId); + } + } + return jsonDoc; +} /** * blobToJsonDoc @@ -21,29 +134,27 @@ import { FatBinaryDoc, FatJsonDoc, FatTextDoc, JsonDoc } from '../types'; export function blobToJsonDoc ( shortId: string, readBlobResult: ReadBlobResult, - withMetadata: boolean + withMetadata: boolean, + serializeFormat: SerializeFormat, + extension: string ): FatJsonDoc | JsonDoc { - try { - const text = utf8decode(readBlobResult.blob); - const jsonDoc = (JSON.parse(text) as unknown) as JsonDoc; - if (jsonDoc._id !== undefined) { - // Overwrite _id property by shortId (_id without collectionPath) if JsonDoc is created by GitDocumentedDB (_id !== undefined). - jsonDoc._id = shortId; - } - if (withMetadata) { - const fatJsonDoc: FatJsonDoc = { - _id: shortId, - name: shortId + JSON_EXT, - fileOid: readBlobResult.oid, - type: 'json', - doc: jsonDoc, - }; - return fatJsonDoc; - } - return jsonDoc; - } catch { - throw new Err.InvalidJsonObjectError(shortId); + const text = utf8decode(readBlobResult.blob); + const jsonDoc = textToJsonDoc(text, serializeFormat, extension, shortId); + if (jsonDoc._id !== undefined) { + // Overwrite _id property by shortId (_id without collectionPath) if JsonDoc is created by GitDocumentedDB (_id !== undefined). + jsonDoc._id = shortId; } + if (withMetadata) { + const fatJsonDoc: FatJsonDoc = { + _id: shortId, + name: shortId + serializeFormat.extension(jsonDoc), + fileOid: readBlobResult.oid, + type: 'json', + doc: jsonDoc, + }; + return fatJsonDoc; + } + return jsonDoc; } /** @@ -51,16 +162,15 @@ export function blobToJsonDoc ( * * @throws {@link Err.InvalidJsonObjectError} */ +// eslint-disable-next-line complexity export function blobToJsonDocWithoutOverwrittenId ( - readBlobResult: ReadBlobResult + readBlobResult: ReadBlobResult, + serializeFormat: SerializeFormat, + extension: string ): JsonDoc { - try { - const text = utf8decode(readBlobResult.blob); - const jsonDoc = (JSON.parse(text) as unknown) as JsonDoc; - return jsonDoc; - } catch (e) { - throw new Err.InvalidJsonObjectError(''); - } + const text = utf8decode(readBlobResult.blob); + const jsonDoc = textToJsonDoc(text, serializeFormat, extension); + return jsonDoc; } /** @@ -136,3 +246,16 @@ export async function readLatestBlob ( filepath: fullDocPath, }).catch(() => undefined); } + +/** + * Check if two FatDocs are the same. + */ +export function isSameFatDoc (a: FatDoc, b: FatDoc) { + if (a.type !== b.type) { + return false; + } + if (a.type === 'json') { + return JSON.stringify(a) === JSON.stringify(b); + } + return a === b; +} diff --git a/src/crud/delete.ts b/src/crud/delete.ts index cf8e6259..8f7153d9 100644 --- a/src/crud/delete.ts +++ b/src/crud/delete.ts @@ -19,12 +19,13 @@ import { normalizeCommit } from '../utils'; * Implementation of delete() * * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.UndefinedDBError} (from deleteWorker) - * @throws {@link Err.RepositoryNotOpenError} (deleteWorker) - * @throws {@link Err.DocumentNotFoundError} (from deleteWorker) - * @throws {@link Err.CannotDeleteDataError} (from deleteWorker) + * @throws # Errors from deleteWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotDeleteDataError} * * @internal */ @@ -38,6 +39,9 @@ export function deleteImpl ( if (gitDDB.isClosing) { return Promise.reject(new Err.DatabaseClosingError()); } + if (!gitDDB.isOpened) { + return Promise.reject(new Err.RepositoryNotOpenError()); + } options ??= { commitMessage: undefined, @@ -80,7 +84,6 @@ export function deleteImpl ( * Remove and commit a file * * @throws {@link Err.UndefinedDBError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.DocumentNotFoundError} * @throws {@link Err.CannotDeleteDataError} */ @@ -94,10 +97,6 @@ export async function deleteWorker ( throw new Err.UndefinedDBError(); } - if (!gitDDB.isOpened) { - throw new Err.RepositoryNotOpenError(); - } - const fullDocPath = collectionPath + shortName; if (collectionPath === undefined || shortName === undefined || fullDocPath === '') { @@ -161,8 +160,8 @@ export async function deleteWorker ( /* not empty */ }); } - } catch (err) { - return Promise.reject(new Err.CannotDeleteDataError(err.message)); + } catch (err: unknown) { + return Promise.reject(new Err.CannotDeleteDataError((err as Error).message)); } return { diff --git a/src/crud/find.ts b/src/crud/find.ts index 775f0d5c..f3f8c470 100644 --- a/src/crud/find.ts +++ b/src/crud/find.ts @@ -7,8 +7,8 @@ */ import fs from 'fs'; -import { readTree, resolveRef, TreeEntry, TreeObject } from 'isomorphic-git'; -import { GIT_DOCUMENTDB_METADATA_DIR, JSON_EXT } from '../const'; +import { readBlob, readTree, resolveRef, TreeEntry, TreeObject } from 'isomorphic-git'; +import { GIT_DOCUMENTDB_METADATA_DIR } from '../const'; import { Err } from '../error'; import { Doc, @@ -19,9 +19,15 @@ import { FatTextDoc, FindOptions, JsonDoc, + SerializeFormat, } from '../types'; import { GitDDBInterface } from '../types_gitddb'; -import { blobToBinary, blobToJsonDoc, blobToText, readLatestBlob } from './blob'; +import { blobToBinary, blobToJsonDoc, blobToText } from './blob'; +import { + getBinaryDocFromWorkingDir, + getJsonDocFromWorkingDir, + getTextDocFromWorkingDir, +} from './get'; /** * Implementation of find() @@ -34,6 +40,7 @@ import { blobToBinary, blobToJsonDoc, blobToText, readLatestBlob } from './blob' export async function findImpl ( gitDDB: GitDDBInterface, collectionPath: string, + serializeFormat: SerializeFormat, findOnlyJson: boolean, withMetadata: boolean, options?: FindOptions @@ -41,7 +48,6 @@ export async function findImpl ( if (gitDDB.isClosing) { return Promise.reject(new Err.DatabaseClosingError()); } - if (!gitDDB.isOpened) { return Promise.reject(new Err.RepositoryNotOpenError()); } @@ -57,7 +63,7 @@ export async function findImpl ( options.prefix ??= ''; options.prefix = collectionPath + options.prefix; - const commitOid = await resolveRef({ fs, dir: gitDDB.workingDir, ref: 'main' }); + const commitOid = await resolveRef({ fs, dir: gitDDB.workingDir, ref: 'HEAD' }); // Normalize prefix and targetDir let prefix = options!.prefix; @@ -143,43 +149,104 @@ export async function findImpl ( } } else { - if (findOnlyJson && !fullDocPath.endsWith('.json')) { + if (findOnlyJson && !serializeFormat.hasObjectExtension(fullDocPath)) { continue; } - // eslint-disable-next-line no-await-in-loop - const readBlobResult = await readLatestBlob(gitDDB.workingDir, fullDocPath); - // Skip if cannot read - if (readBlobResult) { - const docType: DocType = - options.forceDocType ?? (fullDocPath.endsWith('.json') ? 'json' : 'text'); - if (docType === 'text') { - // TODO: select binary or text by .gitattribtues - } - const shortName = fullDocPath.replace(new RegExp('^' + collectionPath), ''); - if (docType === 'json') { - const shortId = shortName.replace(new RegExp(JSON_EXT + '$'), ''); - if (withMetadata) { - docs.push(blobToJsonDoc(shortId, readBlobResult, true) as FatJsonDoc); - } - else { - docs.push(blobToJsonDoc(shortId, readBlobResult, false) as JsonDoc); + + const docType: DocType = + options.forceDocType ?? + (serializeFormat.hasObjectExtension(fullDocPath) ? 'json' : 'text'); + if (docType === 'text') { + // TODO: select binary or text by .gitattribtues + } + const shortName = fullDocPath.replace(new RegExp('^' + collectionPath), ''); + + if (docType === 'json') { + const [, extension] = fullDocPath.match(/.+(\..+?)$/)!; + const shortId = serializeFormat.removeExtension(shortName); + if (withMetadata) { + // eslint-disable-next-line no-await-in-loop + const readBlobResult = await readBlob({ + fs, + dir: gitDDB.workingDir, + oid: commitOid, + filepath: fullDocPath, + }).catch(() => undefined); + // Skip if cannot read + if (readBlobResult) { + docs.push( + blobToJsonDoc( + shortId, + readBlobResult, + true, + serializeFormat, + extension + ) as FatJsonDoc + ); } } - else if (docType === 'text') { - if (withMetadata) { + else { + docs.push( + // eslint-disable-next-line no-await-in-loop + (await getJsonDocFromWorkingDir( + gitDDB, + shortName, + collectionPath, + serializeFormat + )) as JsonDoc + ); + } + } + else if (docType === 'text') { + if (withMetadata) { + // eslint-disable-next-line no-await-in-loop + const readBlobResult = await readBlob({ + fs, + dir: gitDDB.workingDir, + oid: commitOid, + filepath: fullDocPath, + }).catch(() => undefined); + // Skip if cannot read + if (readBlobResult) { docs.push(blobToText(shortName, readBlobResult, true) as FatTextDoc); } - else { - docs.push(blobToText(shortName, readBlobResult, false) as string); - } } - else if (docType === 'binary') { - if (withMetadata) { + else { + docs.push( + // eslint-disable-next-line no-await-in-loop + (await getTextDocFromWorkingDir( + gitDDB, + shortName, + collectionPath, + serializeFormat + )) as string + ); + } + } + else if (docType === 'binary') { + if (withMetadata) { + // eslint-disable-next-line no-await-in-loop + const readBlobResult = await readBlob({ + fs, + dir: gitDDB.workingDir, + oid: commitOid, + filepath: fullDocPath, + }).catch(() => undefined); + // Skip if cannot read + if (readBlobResult) { docs.push(blobToBinary(shortName, readBlobResult, true) as FatBinaryDoc); } - else { - docs.push(blobToBinary(shortName, readBlobResult, false) as Uint8Array); - } + } + else { + docs.push( + // eslint-disable-next-line no-await-in-loop + (await getBinaryDocFromWorkingDir( + gitDDB, + shortName, + collectionPath, + serializeFormat + )) as Uint8Array + ); } } } diff --git a/src/crud/get.ts b/src/crud/get.ts index 48fa2951..1681db0e 100644 --- a/src/crud/get.ts +++ b/src/crud/get.ts @@ -6,8 +6,9 @@ * found in the LICENSE file in the root directory of gitDDB source tree. */ +import path from 'path'; +import fs from 'fs-extra'; import { ReadBlobResult } from 'isomorphic-git'; -import { JSON_EXT } from '../const'; import { GitDDBInterface } from '../types_gitddb'; import { Err } from '../error'; import { @@ -17,6 +18,8 @@ import { GetInternalOptions, GetOptions, HistoryOptions, + JsonDoc, + SerializeFormat, } from '../types'; import { blobToBinary, @@ -25,9 +28,128 @@ import { blobToText, readBlobByOid, readLatestBlob, + textToJsonDoc, } from './blob'; import { readOldBlob } from './history'; +/** + * Read json file from working directory. + * This is x10 faster than readBlob() from loose object, + * x100 faster than readBlob() from packed object. + * + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} + * @throws {@link Err.InvalidJsonObjectError} + */ +export async function getJsonDocFromWorkingDir ( + gitDDB: GitDDBInterface, + shortName: string, + collectionPath: string, + serializeFormat: SerializeFormat +): Promise { + if (gitDDB.isClosing) { + throw new Err.DatabaseClosingError(); + } + if (!gitDDB.isOpened) { + return Promise.reject(new Err.RepositoryNotOpenError()); + } + const fullDocPath = collectionPath + shortName; + const shortId = serializeFormat.removeExtension(shortName); + + if (serializeFormat.format === 'json') { + const jsonDoc = await fs.readJSON(gitDDB.workingDir + '/' + fullDocPath).catch(err => { + if (err instanceof SyntaxError) { + throw new Err.InvalidJsonObjectError(shortId); + } + else return undefined; + }); + if (jsonDoc === undefined) return undefined; + if (jsonDoc._id !== undefined) { + // Overwrite _id property by shortId (_id without collectionPath) if JsonDoc is created by GitDocumentedDB (_id !== undefined). + jsonDoc._id = shortId; + } + return jsonDoc; + } + + const extMatch = fullDocPath.match(/.+(\..+?)$/)!; + let extension = ''; + if (extMatch) { + extension = extMatch[1]; + } + const text = await fs + .readFile(gitDDB.workingDir + '/' + fullDocPath, 'utf-8') + .catch(() => { + return undefined; + }); + if (text === undefined) return undefined; + const jsonDoc = textToJsonDoc(text, serializeFormat, extension, shortId); + if (jsonDoc._id !== undefined) { + // Overwrite _id property by shortId (_id without collectionPath) if JsonDoc is created by GitDocumentedDB (_id !== undefined). + jsonDoc._id = shortId; + } + return jsonDoc; +} + +/** + * Read text file from working directory. + * This is x10 faster than readBlob() from loose object, + * x100 faster than readBlob() from packed object. + * + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} + * @throws {@link Err.InvalidJsonObjectError} + */ +export async function getTextDocFromWorkingDir ( + gitDDB: GitDDBInterface, + shortName: string, + collectionPath: string, + serializeFormat: SerializeFormat +): Promise { + if (gitDDB.isClosing) { + throw new Err.DatabaseClosingError(); + } + if (!gitDDB.isOpened) { + return Promise.reject(new Err.RepositoryNotOpenError()); + } + const fullDocPath = collectionPath + shortName; + const textDoc = await fs + .readFile(gitDDB.workingDir + '/' + fullDocPath, 'utf-8') + .catch(() => { + return undefined; + }); + if (textDoc === undefined) return undefined; + return textDoc; +} + +/** + * Read binary file from working directory. + * This is x10 faster than readBlob() from loose object, + * x100 faster than readBlob() from packed object. + * + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} + * @throws {@link Err.InvalidJsonObjectError} + */ +export async function getBinaryDocFromWorkingDir ( + gitDDB: GitDDBInterface, + shortName: string, + collectionPath: string, + serializeFormat: SerializeFormat +): Promise { + if (gitDDB.isClosing) { + throw new Err.DatabaseClosingError(); + } + if (!gitDDB.isOpened) { + return Promise.reject(new Err.RepositoryNotOpenError()); + } + const fullDocPath = collectionPath + shortName; + const binaryDoc = await fs.readFile(gitDDB.workingDir + '/' + fullDocPath).catch(() => { + return undefined; + }); + if (binaryDoc === undefined) return undefined; + return binaryDoc; +} + /** * Common implementation of get-like commands * @@ -40,6 +162,7 @@ export async function getImpl ( gitDDB: GitDDBInterface, shortName: string, collectionPath: string, + serializeFormat: SerializeFormat, options?: GetOptions, internalOptions?: GetInternalOptions, historyOptions?: HistoryOptions @@ -47,9 +170,8 @@ export async function getImpl ( if (gitDDB.isClosing) { throw new Err.DatabaseClosingError(); } - if (!gitDDB.isOpened) { - throw new Err.RepositoryNotOpenError(); + return Promise.reject(new Err.RepositoryNotOpenError()); } options ??= { @@ -99,17 +221,29 @@ export async function getImpl ( if (readBlobResult === undefined) return undefined; const docType: DocType = - options.forceDocType ?? (fullDocPath.endsWith('.json') ? 'json' : 'text'); + options.forceDocType ?? + (serializeFormat.hasObjectExtension(fullDocPath) ? 'json' : 'text'); if (docType === 'text') { // TODO: select binary or text by .gitattribtues } if (docType === 'json') { + const extMatch = fullDocPath.match(/.+(\..+?)$/)!; + let extension = ''; + if (extMatch) { + extension = extMatch[1]; + } if (internalOptions.oid !== '') { - return blobToJsonDocWithoutOverwrittenId(readBlobResult); + return blobToJsonDocWithoutOverwrittenId(readBlobResult, serializeFormat, extension); } - const shortId = shortName.replace(new RegExp(JSON_EXT + '$'), ''); - return blobToJsonDoc(shortId, readBlobResult, internalOptions.withMetadata); + const shortId = serializeFormat.removeExtension(shortName); + return blobToJsonDoc( + shortId, + readBlobResult, + internalOptions.withMetadata, + serializeFormat, + extension + ); } else if (docType === 'text') { return blobToText(shortName, readBlobResult, internalOptions.withMetadata); diff --git a/src/crud/history.ts b/src/crud/history.ts index 4b7717d6..7f4e3225 100644 --- a/src/crud/history.ts +++ b/src/crud/history.ts @@ -8,10 +8,17 @@ import { log, readBlob, ReadBlobResult } from 'isomorphic-git'; import fs from 'fs-extra'; -import { Doc, DocType, FatDoc, GetOptions, HistoryFilter, HistoryOptions } from '../types'; +import { + Doc, + DocType, + FatDoc, + GetOptions, + HistoryFilter, + HistoryOptions, + SerializeFormat, +} from '../types'; import { GitDDBInterface } from '../types_gitddb'; import { Err } from '../error'; -import { JSON_EXT } from '../const'; import { blobToBinary, blobToJsonDoc, blobToText } from './blob'; /** @@ -19,13 +26,16 @@ import { blobToBinary, blobToJsonDoc, blobToText } from './blob'; * * @throws {@link Err.DatabaseClosingError} * @throws {@link Err.RepositoryNotOpenError} - * @throws {@link Err.InvalidJsonObjectError} (from blobToJsonDoc) + * + * @throws # Errors from blobToJsonDoc + * @throws {@link Err.InvalidJsonObjectError} */ // eslint-disable-next-line complexity export async function getHistoryImpl ( gitDDB: GitDDBInterface, shortName: string, collectionPath: string, + serializeFormat: SerializeFormat, historyOptions?: HistoryOptions, options?: GetOptions, withMetaData = false @@ -33,9 +43,8 @@ export async function getHistoryImpl ( if (gitDDB.isClosing) { throw new Err.DatabaseClosingError(); } - if (!gitDDB.isOpened) { - throw new Err.RepositoryNotOpenError(); + return Promise.reject(new Err.RepositoryNotOpenError()); } options ??= { @@ -45,7 +54,8 @@ export async function getHistoryImpl ( const fullDocPath = collectionPath + shortName; const docType: DocType = - options.forceDocType ?? (fullDocPath.endsWith('.json') ? 'json' : 'text'); + options.forceDocType ?? + (serializeFormat.hasObjectExtension(fullDocPath) ? 'json' : 'text'); if (docType === 'text') { // TODO: select binary or text by .gitattribtues @@ -87,14 +97,31 @@ export async function getHistoryImpl ( docArray.push(undefined); } else if (docType === 'json') { - const shortId = shortName.replace(new RegExp(JSON_EXT + '$'), ''); + const [, extension] = fullDocPath.match(/.+(\..+?)$/)!; + const shortId = serializeFormat.removeExtension(shortName); // eslint-disable-next-line max-depth if (withMetaData) { - docArray.push(blobToJsonDoc(shortId, readBlobResult, true) as FatDoc); + docArray.push( + blobToJsonDoc( + shortId, + readBlobResult, + true, + serializeFormat, + extension + ) as FatDoc + ); } else { - docArray.push(blobToJsonDoc(shortId, readBlobResult, false) as Doc); + docArray.push( + blobToJsonDoc( + shortId, + readBlobResult, + false, + serializeFormat, + extension + ) as Doc + ); } } else if (docType === 'text') { diff --git a/src/crud/put.ts b/src/crud/put.ts index 0bb07f7b..b8e0b907 100644 --- a/src/crud/put.ts +++ b/src/crud/put.ts @@ -19,14 +19,15 @@ import { Err } from '../error'; * Common implementation of put-like commands. * * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.UndefinedDBError} (from putWorker) - * @throws {@link Err.RepositoryNotOpenError} (from putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.SameIdExistsError} (from putWorker) - * @throws {@link Err.DocumentNotFoundError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws {@link Err.UndefinedDBError} + * @throws {@link Err.CannotCreateDirectoryError} + * @throws {@link Err.SameIdExistsError} + * @throws {@link Err.DocumentNotFoundError} + * @throws {@link Err.CannotWriteDataError} * * @internal */ @@ -42,13 +43,18 @@ export function putImpl ( if (gitDDB.isClosing) { return Promise.reject(new Err.DatabaseClosingError()); } + if (!gitDDB.isOpened) { + return Promise.reject(new Err.RepositoryNotOpenError()); + } options ??= { commitMessage: undefined, insertOrUpdate: undefined, taskId: undefined, enqueueCallback: undefined, + debounceTime: undefined, }; + options.debounceTime ??= -1; const fullDocPath = collectionPath + shortName; @@ -64,6 +70,7 @@ export function putImpl ( shortId, shortName, collectionPath, + debounceTime: options!.debounceTime, func: (beforeResolve, beforeReject) => putWorker( gitDDB, @@ -93,7 +100,6 @@ export function putImpl ( * Add and commit a file * * @throws {@link Err.UndefinedDBError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.CannotCreateDirectoryError} * @throws {@link Err.SameIdExistsError} * @throws {@link Err.DocumentNotFoundError} @@ -111,9 +117,6 @@ export async function putWorker ( throw new Err.UndefinedDBError(); } - if (!gitDDB.isOpened) { - throw new Err.RepositoryNotOpenError(); - } const fullDocPath = collectionPath + shortName; let fileOid: string; @@ -125,25 +128,13 @@ export async function putWorker ( }); try { - await fs.writeFile(filePath, data); - const headCommit = await git .resolveRef({ fs, dir: gitDDB.workingDir, ref: 'HEAD' }) .catch(() => undefined); - const oldEntry = - headCommit === undefined - ? undefined - : await git - .readBlob({ - fs, - dir: gitDDB.workingDir, - oid: headCommit, - filepath: fullDocPath, - }) - .catch(() => undefined); + const oldEntryExists = fs.existsSync(filePath); - if (oldEntry) { + if (oldEntryExists) { if (insertOrUpdate === 'insert') return Promise.reject(new Err.SameIdExistsError()); insertOrUpdate ??= 'update'; } @@ -152,6 +143,7 @@ export async function putWorker ( return Promise.reject(new Err.DocumentNotFoundError()); insertOrUpdate ??= 'insert'; } + await fs.writeFile(filePath, data); await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); @@ -178,8 +170,8 @@ export async function putWorker ( oid: commitOid, }); commit = normalizeCommit(readCommitResult); - } catch (err) { - throw new Err.CannotWriteDataError(err.message); + } catch (err: unknown) { + throw new Err.CannotWriteDataError((err as Error).message); } return { diff --git a/src/error.ts b/src/error.ts index af5ed7f0..a54b8e47 100644 --- a/src/error.ts +++ b/src/error.ts @@ -132,7 +132,7 @@ export namespace Err { */ export class InvalidJsonFileExtensionError extends BaseError { constructor () { - super(`JSON file extension must be .json`); + super(`JSON file extension is invalid`); } } @@ -145,6 +145,15 @@ export namespace Err { } } + /** + * @public + */ + export class UndefinedPersonalAccessTokenError extends BaseError { + constructor () { + super(`Personal Access Token of your GitHub account is needed.`); + } + } + /** * @public */ @@ -230,25 +239,6 @@ export namespace Err { } } - /** - * @public - */ - export class InvalidSSHKeyPathError extends BaseError { - constructor () { - const e = `Invalid SSH key path`; - super(e); - } - } - - /** - * @public - */ - export class InvalidURLError extends BaseError { - constructor (url: unknown) { - super(`Invalid url: ${url}'`); - } - } - /** * @public */ @@ -258,53 +248,6 @@ export namespace Err { } } - /** - * @public - */ - export class RemoteRepositoryNotFoundError extends BaseError { - constructor (url: unknown) { - super( - `Repository does not exist, or you do not have permission to access the repository: ${url}` - ); - } - } - - /** - * @public - */ - export class PushPermissionDeniedError extends BaseError { - constructor (mes: unknown) { - super(`Permission denied to push to the repository: ${mes}`); - } - } - - /** - * @public - */ - export class FetchPermissionDeniedError extends BaseError { - constructor (mes: unknown) { - super(`Permission denied to fetch to the repository: ${mes}`); - } - } - - /** - * @public - */ - export class FetchConnectionFailedError extends BaseError { - constructor (mes: unknown) { - super(`Fetch connection failed: ${mes}`); - } - } - - /** - * @public - */ - export class PushConnectionFailedError extends BaseError { - constructor (mes: unknown) { - super(`Push connection failed: ${mes}`); - } - } - /** * @public */ @@ -317,16 +260,6 @@ Call removeRemote() before register it again.` } } - /** - * @public - */ - export class InvalidAuthenticationTypeError extends BaseError { - constructor (type: string) { - super(`Authentication type must be one of the following values: 'github', 'ssh'. -Current value is '${type}'`); - } - } - /** * @public */ @@ -338,24 +271,6 @@ Current value is '${type}'`); } } - /** - * @public - */ - export class UndefinedPersonalAccessTokenError extends BaseError { - constructor () { - super(`Personal Access Token of your GitHub account is needed.`); - } - } - - /** - * @public - */ - export class SyncWorkerFetchError extends BaseError { - constructor (mes: string) { - super(`Fetch error in sync worker: ${mes}`); - } - } - /** * @public */ @@ -374,35 +289,6 @@ Current value is '${type}'`); } } - /** - * @public - */ - export class InvalidRepositoryURLError extends BaseError { - constructor (url: unknown) { - super(`Repository URL is invalid: ${url}`); - } - } - - /** - * @public - */ - export class NoMergeBaseFoundError extends BaseError { - constructor () { - super(`No merge base found`); - } - } - - /** - * @public - */ - export class UnfetchedCommitExistsError extends BaseError { - constructor () { - super( - 'Cannot push because a reference that you are trying to update on the remote contains commits that are not present locally.' - ); - } - } - /** * @public */ @@ -430,6 +316,15 @@ Current value is '${type}'`); } } + /** + * @public + */ + export class InvalidConflictResolutionStrategyError extends BaseError { + constructor () { + super(`Conflict resolution strategy is invalid.`); + } + } + /** * @public */ @@ -453,7 +348,7 @@ Current value is '${type}'`); /** * @public */ - export class CannotConnectError extends BaseError { + export class CannotConnectRemoteRepositoryError extends BaseError { constructor (public retry: number, url: string, mes: string) { super(`Cannot connect to ${url}: ${mes}`); } @@ -477,15 +372,6 @@ Current value is '${type}'`); } } - /** - * @public - */ - export class HTTPNetworkError extends BaseError { - constructor (mes: unknown) { - super(`HTTPNetworkError: ${mes}`); - } - } - /** * @public */ @@ -549,15 +435,6 @@ Current value is '${type}'`); } } - /** - * @public - */ - export class RemoteRepositoryConnectError extends BaseError { - constructor (mes: unknown) { - super(`Error in RemoteRepository#connect(): ${mes}`); - } - } - /** * @public */ @@ -567,15 +444,6 @@ Current value is '${type}'`); } } - /** - * @public - */ - export class GitPushError extends BaseError { - constructor (mes: string) { - super(`Push error in Git : ${mes}`); - } - } - /** * @public */ @@ -613,4 +481,13 @@ Current value is '${type}'`); super(`Combine database failed: ${mes})`); } } + + /** + * @public + */ + export class NoMergeBaseFoundError extends BaseError { + constructor () { + super(`No merge base found`); + } + } } diff --git a/src/git_documentdb.ts b/src/git_documentdb.ts index 7a44c6b9..55c76084 100644 --- a/src/git_documentdb.ts +++ b/src/git_documentdb.ts @@ -7,18 +7,19 @@ */ import path from 'path'; -import nodegit from '@sosuisen/nodegit'; import git from 'isomorphic-git'; import fs from 'fs-extra'; import rimraf from 'rimraf'; -import { Logger, TLogLevelName } from 'tslog'; +import { ILogObject, Logger, TLogLevelName } from 'tslog'; import { ulid } from 'ulid'; +import { RemoteEngine } from './remote/remote_engine'; import { Err } from './error'; import { Collection } from './collection'; import { Validator } from './validator'; import { CollectionOptions, CollectionPath, + ColoredLogger, DatabaseCloseOption, DatabaseInfo, DatabaseOpenResult, @@ -35,11 +36,14 @@ import { JsonDoc, NormalizedCommit, OpenOptions, + PluginTypes, PutOptions, PutResult, PutResultJsonDoc, RemoteOptions, Schema, + SerializeFormat, + SerializeFormatLabel, SyncCallback, SyncEvent, SyncResult, @@ -53,40 +57,21 @@ import { DATABASE_VERSION, DEFAULT_LOCAL_DIR, DEFAULT_LOG_LEVEL, + FILE_CREATE_TIMEOUT, FILE_REMOVE_TIMEOUT, FIRST_COMMIT_MESSAGE, - GIT_DOCUMENTDB_APP_INFO_ID, GIT_DOCUMENTDB_INFO_ID, - JSON_EXT, - PUT_APP_INFO_MESSAGE, + JSON_POSTFIX, SET_DATABASE_ID_MESSAGE, } from './const'; -import { normalizeCommit, toSortedJSONString } from './utils'; +import { normalizeCommit, sleep, toSortedJSONString } from './utils'; import { SyncEventInterface, SyncInterface } from './types_sync'; import { CRUDInterface } from './types_crud_interface'; import { CollectionInterface, ICollection } from './types_collection'; +import { blobToJsonDoc, readLatestBlob } from './crud/blob'; -interface RepositoryInitOptions { - description?: string; - initialHead?: string; - flags?: number; // https://libgit2.org/libgit2/#HEAD/type/git_repository_init_flag_t - mode?: number; // https://libgit2.org/libgit2/#HEAD/type/git_repository_init_mode_t - originUrl?: string; - templatePath?: string; - version?: number; - workdirPath?: string; -} -/* - const repositoryInitOptionFlags = { - GIT_REPOSITORY_INIT_BARE: 1, - GIT_REPOSITORY_INIT_NO_REINIT: 2, - GIT_REPOSITORY_INIT_NO_DOTGIT_DIR: 4, - GIT_REPOSITORY_INIT_MKDIR: 8, - GIT_REPOSITORY_INIT_MKPATH: 16, - GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE: 32, - GIT_REPOSITORY_INIT_RELATIVE_GITLINK: 64, - }; - */ +import * as remote_isomorphic_git from './plugin/remote-isomorphic-git'; +import { SerializeFormatFrontMatter, SerializeFormatJSON } from './serialize_format'; /** * Get database ID @@ -97,6 +82,16 @@ export function generateDatabaseId () { return ulid(Date.now()); } +const INITIAL_DATABASE_OPEN_RESULT: DatabaseOpenResult = { + dbId: '', + creator: '', + version: '', + isNew: false, + isCreatedByGitDDB: true, + isValidVersion: true, + serialize: 'json', +}; + /** * Main class of GitDocumentDB * @@ -107,25 +102,47 @@ export function generateDatabaseId () { */ export class GitDocumentDB implements GitDDBInterface, CRUDInterface, CollectionInterface, SyncEventInterface { + static plugin (obj: any) { + const type: PluginTypes = obj.type; + if (type === 'remote') { + if (obj.name !== undefined) { + // @ts-ignore + RemoteEngine[obj.name] = {}; + Object.keys(obj).forEach(function (id) { + // Set to Remote object + // @ts-ignore + RemoteEngine[obj.name][id] = obj[id]; + }); + } + } + else { + Object.keys(obj).forEach(function (id) { + // Set to Instance property + // @ts-ignore + GitDocumentDB.prototype[id] = obj[id]; + }); + } + } + /*********************************************** * Private properties ***********************************************/ - private _currentRepository: nodegit.Repository | undefined; - private _synchronizers: { [url: string]: Sync } = {}; private _dbOpenResult: DatabaseOpenResult = { - dbId: '', - creator: '', - version: '', - isNew: false, - isCreatedByGitDDB: true, - isValidVersion: true, + ...INITIAL_DATABASE_OPEN_RESULT, }; /*********************************************** * Public properties (readonly) ***********************************************/ + /** + * Serialize format for json object + */ + private _serializeFormat!: SerializeFormatJSON | SerializeFormatFrontMatter; + get serializeFormat () { + return this._serializeFormat; + } /** * Default Git branch @@ -180,14 +197,105 @@ export class GitDocumentDB return this._dbOpenResult.dbId; } - private _logger!: Logger; // Use definite assignment assertion + private _tsLogger!: Logger; + /** + * Get logger + * + * @readonly + * @public + */ + get tsLogger (): Logger { + return this._tsLogger; + } + + // Use definite assignment assertion + private _logger: ColoredLogger = { + silly: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (this._logColorEnabled && colorTag !== undefined) { + this._tsLogger.silly(colorTag()`${mes}`); + } + else { + this._tsLogger.silly(mes); + } + }, + debug: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (this._logColorEnabled && colorTag !== undefined) { + this._tsLogger.debug(colorTag()`${mes}`); + } + else { + this._tsLogger.debug(mes); + } + }, + trace: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (this._logColorEnabled && colorTag !== undefined) { + this._tsLogger.trace(colorTag()`${mes}`); + } + else { + this._tsLogger.trace(mes); + } + }, + info: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (this._logColorEnabled && colorTag !== undefined) { + this._tsLogger.info(colorTag()`${mes}`); + } + else { + this._tsLogger.info(mes); + } + }, + warn: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (this._logColorEnabled && colorTag !== undefined) { + this._tsLogger.warn(colorTag()`${mes}`); + } + else { + this._tsLogger.warn(mes); + } + }, + error: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (this._logColorEnabled && colorTag !== undefined) { + this._tsLogger.error(colorTag()`${mes}`); + } + else { + this._tsLogger.error(mes); + } + }, + fatal: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (this._logColorEnabled && colorTag !== undefined) { + this._tsLogger.fatal(colorTag()`${mes}`); + } + else { + this._tsLogger.fatal(mes); + } + }, + }; + /** * Get logger * * @readonly * @public */ - get logger (): Logger { + get logger (): ColoredLogger { return this._logger; } @@ -202,6 +310,17 @@ export class GitDocumentDB return this._schema; } + private _logToTransport: ((logObject: ILogObject) => void) | undefined; + /** + * logToTransport function for all log levels. See https://tslog.js.org/#/?id=transports + * + * @readonly + * @public + */ + get logToTransport (): ((logObject: ILogObject) => void) | undefined { + return this._logToTransport; + } + private _taskQueue: TaskQueue; /** * Task queue @@ -246,6 +365,8 @@ export class GitDocumentDB return this._rootCollection as ICollection; } + private _logColorEnabled: boolean; + /*********************************************** * Public properties ***********************************************/ @@ -262,13 +383,27 @@ export class GitDocumentDB set logLevel (level: TLogLevelName) { this._logLevel = level; - this._logger = new Logger({ + this._tsLogger = new Logger({ name: this._dbName, minLevel: level as TLogLevelName, displayDateTime: false, displayFunctionName: false, displayFilePath: 'hidden', }); + if (this.logToTransport) { + this._tsLogger.attachTransport( + { + silly: this.logToTransport, + debug: this.logToTransport, + trace: this.logToTransport, + info: this.logToTransport, + warn: this.logToTransport, + error: this.logToTransport, + fatal: this.logToTransport, + }, + level + ); + } if (this.taskQueue) this.taskQueue.setLogger(this._logger); } @@ -303,6 +438,7 @@ export class GitDocumentDB * * @public */ + // eslint-disable-next-line complexity constructor (options: DatabaseOptions & CollectionOptions) { if (options.dbName === undefined || options.dbName === '') { throw new Err.UndefinedDatabaseNameError(); @@ -313,11 +449,21 @@ export class GitDocumentDB this._schema = options.schema ?? { json: { - idOfSubtree: undefined, + keyInArrayedObject: undefined, plainTextProperties: undefined, }, }; + this._logToTransport = options.logToTransport; + + const format: SerializeFormatLabel = options.serialize ?? 'json'; + if (format === 'front-matter') { + this._serializeFormat = new SerializeFormatFrontMatter(); + } + else { + this._serializeFormat = new SerializeFormatJSON(); + } + // Get full-path this._workingDir = path.resolve(this._localDir, this._dbName); @@ -342,10 +488,23 @@ export class GitDocumentDB // Set logLevel after initializing taskQueue. this.logLevel = options.logLevel ?? DEFAULT_LOG_LEVEL; + this._logColorEnabled = options.logColorEnabled ?? true; + const collectionOptions = { namePrefix: options?.namePrefix ?? '', + debounceTime: options?.debounceTime ?? -1, + idGenerator: options?.idGenerator, }; this._rootCollection = new Collection(this, '', undefined, collectionOptions); + + // @ts-ignore + RemoteEngine[remote_isomorphic_git.name] = {}; + Object.keys(remote_isomorphic_git).forEach(function (id) { + // Set to Remote object + // @ts-ignore + // eslint-disable-next-line import/namespace + RemoteEngine[remote_isomorphic_git.name][id] = remote_isomorphic_git[id]; + }); } /*********************************************** @@ -353,39 +512,83 @@ export class GitDocumentDB ***********************************************/ /** + * Create local repository + * + * @throws {@link Err.CannotCreateDirectoryError} + * + * @throws # from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.SameIdExistsError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotWriteDataError} + * @internal */ private async _createRepository () { - /** - * Create a repository followed by first commit - */ - const options: RepositoryInitOptions = { - initialHead: this.defaultBranch, - }; - this._dbOpenResult.isNew = true; - - this._currentRepository = await nodegit.Repository.initExt( - this._workingDir, - // @ts-ignore - options - ).catch(err => { - return Promise.reject(err); - }); - // First commit const info = { dbId: generateDatabaseId(), creator: DATABASE_CREATOR, version: DATABASE_VERSION, + serialize: this._serializeFormat.format, }; - // Do not use this.put() because it increments TaskQueue.statistics.put. - await putWorker( - this, - '', - GIT_DOCUMENTDB_INFO_ID + JSON_EXT, - toSortedJSONString(info), - FIRST_COMMIT_MESSAGE - ); + + // Retry three times. + // Creating system files sometimes fail just after installing from Squirrel installer of Electron. + const retry = 3; + for (let i = 0; i < retry + 1; i++) { + // eslint-disable-next-line no-await-in-loop + const resEnsure = await fs.ensureDir(this._workingDir).catch((err: Error) => { + if (i >= retry) throw new Err.CannotCreateDirectoryError(err.message); + return 'cannot_create'; + }); + if (resEnsure === 'cannot_create') { + // eslint-disable-next-line no-await-in-loop + await sleep(FILE_CREATE_TIMEOUT); + this.logger.debug('retrying ensureDir in createRepository'); + continue; + } + + // eslint-disable-next-line no-await-in-loop + const resInit = await git + .init({ fs, dir: this._workingDir, defaultBranch: this.defaultBranch }) + .catch((err: Error) => { + if (i >= retry) throw err; + return 'cannot_init'; + }); + if (resInit === 'cannot_init') { + // eslint-disable-next-line no-await-in-loop + await sleep(FILE_CREATE_TIMEOUT); + this.logger.debug('retrying git.init in createRepository'); + continue; + } + + // Do not use this.put() because it increments TaskQueue.statistics.put. + // eslint-disable-next-line no-await-in-loop + const resPut = await putWorker( + this, + '', + GIT_DOCUMENTDB_INFO_ID + JSON_POSTFIX, + toSortedJSONString(info), + FIRST_COMMIT_MESSAGE + ).catch(err => { + if (i >= retry) throw err; + return 'cannot_put'; + }); + if (resPut === 'cannot_put') { + // eslint-disable-next-line no-await-in-loop + await sleep(FILE_CREATE_TIMEOUT); + fs.removeSync(this._workingDir); + this.logger.debug('retrying putWorker in createRepository'); + continue; + } + + break; + } + + this._dbOpenResult.isNew = true; + this._dbOpenResult = { ...this._dbOpenResult, ...info }; } @@ -406,16 +609,25 @@ export class GitDocumentDB * - GitDocumentDB can also load a Git repository that is created by other apps. It almost works; however, correct behavior is not guaranteed if it does not have a valid '.gitddb/'. * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.CannotCreateDirectoryError} - * @throws {@link Err.CannotOpenRepositoryError} * @throws {@link Err.RepositoryNotFoundError} may occurs when openOptions.createIfNotExists is false. * + * @throws # Errors from _createRepository + * @throws - {@link Err.CannotCreateDirectoryError} + * + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.SameIdExistsError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotWriteDataError} + * * @public */ async open (openOptions?: OpenOptions): Promise { if (this.isClosing) { throw new Err.DatabaseClosingError(); } + if (this.isOpened) { this._dbOpenResult.isNew = false; return this._dbOpenResult; @@ -427,50 +639,20 @@ export class GitDocumentDB } openOptions.createIfNotExists ??= true; - /** - * Create directory - */ - await fs.ensureDir(this._workingDir).catch((err: Error) => { - throw new Err.CannotCreateDirectoryError(err.message); - }); - - /** - * Reset - */ - this._synchronizers = {}; - this._dbOpenResult = { - dbId: '', - creator: '', - version: '', - isNew: false, - isCreatedByGitDDB: true, - isValidVersion: true, - }; - this.taskQueue.clear(); - - /** - * nodegit.Repository.open() throws an error if the specified repository does not exist. - * open() also throws an error if the path is invalid or not writable, - */ - try { - this._currentRepository = await nodegit.Repository.open(this._workingDir); - } catch (err) { - const gitDir = this._workingDir + '/.git/'; - if (fs.existsSync(gitDir)) { - // Cannot open though .git directory exists. - throw new Err.CannotOpenRepositoryError(this._workingDir); - } + const gitDir = this._workingDir + '/.git/'; + if (!fs.existsSync(gitDir)) { if (openOptions.createIfNotExists) { - await this._createRepository().catch(e => { - throw new Err.CannotCreateRepositoryError(e.message); - }); + await this._createRepository(); } else { throw new Err.RepositoryNotFoundError(gitDir); } } - await this.loadDbInfo(); + + // Start when no exception + this._taskQueue.start(); + return this._dbOpenResult; } @@ -483,6 +665,7 @@ export class GitDocumentDB * - Queued operations are executed before the database is closed unless it times out. * * @param options - The options specify how to close database. + * * @throws {@link Err.DatabaseClosingError} * @throws {@link Err.DatabaseCloseTimeoutError} * @@ -500,35 +683,24 @@ export class GitDocumentDB options.timeout ??= 10000; // Wait taskQueue - if (this._currentRepository instanceof nodegit.Repository) { - try { - this._isClosing = true; - if (!options.force) { - const isTimeout = await this.taskQueue.waitCompletion(options.timeout); - if (isTimeout) { - return Promise.reject(new Err.DatabaseCloseTimeoutError()); - } + try { + this._isClosing = true; + if (!options.force) { + const isTimeout = await this.taskQueue.waitCompletion(options.timeout); + if (isTimeout) { + return Promise.reject(new Err.DatabaseCloseTimeoutError()); } - } finally { - this.taskQueue.clear(); - - /** - * The types are wrong. Repository does not have free() method. - * See https://github.com/nodegit/nodegit/issues/1817#issuecomment-776844425 - * https://github.com/nodegit/nodegit/pull/1570 - * - * Use cleanup() instead. - * http://carlosmn.github.io/libgit2/#v0.23.0/group/repository/git_repository__cleanup - */ - // this._currentRepository.free(); + } + } finally { + this.taskQueue.stop(); - this._currentRepository.cleanup(); - this._currentRepository = undefined; + this._synchronizers = {}; - this._synchronizers = {}; + this._dbOpenResult = { + ...INITIAL_DATABASE_OPEN_RESULT, + }; - this._isClosing = false; - } + this._isClosing = false; } } @@ -545,6 +717,7 @@ export class GitDocumentDB * - destroy() does not remove localDir (which is specified in constructor). * * @param options - The options specify how to close database. + * * @throws {@link Err.DatabaseClosingError} * @throws {@link Err.DatabaseCloseTimeoutError} * @throws {@link Err.FileRemoveTimeoutError} @@ -557,13 +730,12 @@ export class GitDocumentDB } let closeError: Error | undefined; - if (this._currentRepository !== undefined) { - // NOTICE: options.force is true by default. - options.force = options.force ?? true; - await this.close(options).catch(err => { - closeError = err; - }); - } + // NOTICE: options.force is true by default. + options.force = options.force ?? true; + await this.close(options).catch(err => { + closeError = err; + }); + // If the path does not exist, remove() silently does nothing. // https://github.com/jprichardson/node-fs-extra/blob/master/docs/remove.md // await fs.remove(this._workingDir).catch(err => { @@ -596,7 +768,7 @@ export class GitDocumentDB * @public */ get isOpened (): boolean { - return this._currentRepository !== undefined; + return this._dbOpenResult.dbId !== ''; } /** @@ -620,7 +792,6 @@ export class GitDocumentDB * * @param dirPath - Get collections directly under the dirPath. dirPath is a relative path from localDir. Default is ''. * @returns Promise\ - * @throws {@link Err.RepositoryNotOpenError} * * @public */ @@ -659,34 +830,37 @@ export class GitDocumentDB /** * Synchronize with a remote repository * - * @throws {@link Err.UndefinedRemoteURLError} (from Sync#constructor()) - * @throws {@link Err.IntervalTooSmallError} (from Sync#constructor()) - * - * @throws {@link Err.RepositoryNotFoundError} (from Sync#syncImpl()) - * @throws {@link Err.RemoteRepositoryConnectError} (from Sync#init()) - * @throws {@link Err.PushWorkerError} (from Sync#init()) - * @throws {@link Err.SyncWorkerError} (from Sync#init()) - * * @remarks * Register and synchronize with a remote repository. Do not register the same remote repository again. Call unregisterRemote() before register it again. * + * @throws {@link Err.RemoteAlreadyRegisteredError} + * + * @privateRemarks # from Sync#syncAndGetResultImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} + * + * @throws Errors from constructor of {@link Sync} class. + * @throws Errors from {@link Sync.init} + * * @public */ async sync (options: RemoteOptions): Promise; /** * Synchronize with a remote repository * - * @throws {@link Err.UndefinedRemoteURLError} (from Sync#constructor()) - * @throws {@link Err.IntervalTooSmallError} (from Sync#constructor()) - * - * @throws {@link Err.RepositoryNotFoundError} (from Sync#syncAndGetResultImpl()) - * @throws {@link Err.RemoteRepositoryConnectError} (from Sync#init()) - * @throws {@link Err.PushWorkerError} (from Sync#init()) - * @throws {@link Err.SyncWorkerError} (from Sync#init()) - * * @remarks * Register and synchronize with a remote repository. Do not register the same remote repository again. Call unregisterRemote() before register it again. * + * @throws {@link Err.RemoteAlreadyRegisteredError} + * + * @privateRemarks # from Sync#syncAndGetResultImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} + * + * @throws Errors from constructor of {@link Sync} class. + * @throws Errors from {@link Sync.init} + * + * * @public */ async sync (options: RemoteOptions, getSyncResult: boolean): Promise<[Sync, SyncResult]>; @@ -778,56 +952,55 @@ export class GitDocumentDB this.author.email = email ?? this.author.email; } - /** - * Save app-specific info into .gitddb/app.json - * - * @public - */ - async saveAppInfo (info: { [key: string]: any }) { - // Do not use this.put() because it increments TaskQueue.statistics.put. - await putWorker( - this, - '', - GIT_DOCUMENTDB_APP_INFO_ID + JSON_EXT, - toSortedJSONString(info), - PUT_APP_INFO_MESSAGE - ); - } - - /** - * Load app-specific info from .gitddb/app.json - * - * @returns JSON object. It returns undefined if app.json does not exist. - * - * @public - */ - async loadAppInfo () { - const info = await this.get(GIT_DOCUMENTDB_APP_INFO_ID).catch(() => undefined); - if (info?._id) { - delete info._id; - } - return info; - } - /** * Load DatabaseInfo from .gitddb/info.json * + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.SameIdExistsError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotWriteDataError} + * * @internal */ + // eslint-disable-next-line complexity async loadDbInfo () { - let info = (await this.get(GIT_DOCUMENTDB_INFO_ID).catch( - () => undefined - )) as DatabaseInfo; + let info: DatabaseInfo | undefined; + + // Don't use get() because isOpened is false. + const readBlobResult = await readLatestBlob( + this.workingDir, + GIT_DOCUMENTDB_INFO_ID + JSON_POSTFIX + ).catch(() => undefined); + if (readBlobResult !== undefined) { + try { + info = blobToJsonDoc( + GIT_DOCUMENTDB_INFO_ID, + readBlobResult, + false, + new SerializeFormatJSON(), + JSON_POSTFIX + ) as DatabaseInfo; + } catch (e) {} + } info ??= { dbId: '', creator: '', version: '', + serialize: this._serializeFormat.format, }; info.creator ??= ''; info.version ??= ''; + info.serialize ??= this._serializeFormat.format; + + if (info.serialize !== this._serializeFormat.format) { + // TODO: Change serialize format + } + // Set dbId if not exists. if (!info.dbId) { info.dbId = generateDatabaseId(); @@ -835,7 +1008,7 @@ export class GitDocumentDB await putWorker( this, '', - GIT_DOCUMENTDB_INFO_ID + JSON_EXT, + GIT_DOCUMENTDB_INFO_ID + JSON_POSTFIX, toSortedJSONString(info), SET_DATABASE_ID_MESSAGE ); @@ -863,28 +1036,6 @@ export class GitDocumentDB } } - /** - * Get a current repository - * - * @deprecated This will be removed when NodeGit is replaced with isomorphic-git. - * @public - */ - repository (): nodegit.Repository | undefined { - return this._currentRepository; - } - - /** - * Set repository - * - * @remarks Be aware that it can corrupt the database. - * @deprecated This will be removed when NodeGit is replaced with isomorphic-git. - * @public - */ - setRepository (repos: nodegit.Repository) { - this._currentRepository = undefined; - this._currentRepository = repos; - } - /*********************************************** * Public method (Implementation of CRUDInterface) ***********************************************/ @@ -892,10 +1043,10 @@ export class GitDocumentDB /** * Insert a JSON document if not exists. Otherwise, update it. * - * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. + * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and extension are omitted. * * @remarks - * - The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}.json` on the file system. + * - The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}${extension}` on the file system. * * - If _id is undefined, it is automatically generated. * @@ -903,16 +1054,18 @@ export class GitDocumentDB * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * * @public */ @@ -921,10 +1074,10 @@ export class GitDocumentDB /** * Insert a JSON document if not exists. Otherwise, update it. * - * @param _id - _id is a file path whose .json extension is omitted. + * @param _id - _id is a file path whose extension is omitted. * * @remarks - * - The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. + * - The saved file path is `${GitDocumentDB#workingDir}/${_id}${extension}` on the file system. * * - If _id is undefined, it is automatically generated. * @@ -936,16 +1089,18 @@ export class GitDocumentDB * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * * @public */ @@ -966,14 +1121,14 @@ export class GitDocumentDB /** * Insert a JSON document * - * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. + * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and extension are omitted. * * @remarks * - Throws SameIdExistsError when a document that has the same _id exists. It might be better to use put() instead of insert(). * * - If _id is undefined, it is automatically generated. * - * - The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}.json` on the file system. + * - The saved file path is `${GitDocumentDB#workingDir}/${jsonDoc._id}${extension}` on the file system. * * - This is an alias of GitDocumentDB#rootCollection.insert() * @@ -981,18 +1136,20 @@ export class GitDocumentDB * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.SameIdExistsError} (from putWorker) + * @throws - {@link Err.SameIdExistsError} * * @public */ @@ -1001,12 +1158,12 @@ export class GitDocumentDB /** * Insert a JSON document * - * @param _id - _id is a file path whose .json extension is omitted. + * @param _id - _id is a file path whose extension is omitted. * * @remarks * - Throws SameIdExistsError when a document that has the same id exists. It might be better to use put() instead of insert(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. + * - The saved file path is `${GitDocumentDB#workingDir}/${_id}${extension}` on the file system. * * - If _id is undefined, it is automatically generated. * @@ -1016,18 +1173,20 @@ export class GitDocumentDB * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.SameIdExistsError} (from putWorker) + * @throws - {@link Err.SameIdExistsError} * * @public */ @@ -1050,31 +1209,33 @@ export class GitDocumentDB /** * Update a JSON document * - * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and .json extension are omitted. + * @param jsonDoc - JsonDoc whose _id is shortId. shortId is a file path whose collectionPath and extension are omitted. * * @remarks * - Throws DocumentNotFoundError if a specified document does not exist. It might be better to use put() instead of update(). * * - If _id is undefined, it is automatically generated. * - * - The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. + * - The saved file path is `${GitDocumentDB#workingDir}/${_id}extension` on the file system. * * - This is an alias of GitDocumentDB#rootCollection.update() * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.DocumentNotFoundError} + * @throws - {@link Err.DocumentNotFoundError} * * @public */ @@ -1083,12 +1244,12 @@ export class GitDocumentDB /** * Update a JSON document * - * @param _id - _id is a file path whose .json extension is omitted. + * @param _id - _id is a file path whose extension is omitted. * * @remarks * - Throws DocumentNotFoundError if a specified document does not exist. It might be better to use put() instead of update(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${_id}.json` on the file system. + * - The saved file path is `${GitDocumentDB#workingDir}/${_id}extension` on the file system. * * - An update operation is not skipped even if no change occurred on a specified document. * @@ -1096,18 +1257,20 @@ export class GitDocumentDB * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.DocumentNotFoundError} + * @throws - {@link Err.DocumentNotFoundError} * * @public */ @@ -1131,11 +1294,11 @@ export class GitDocumentDB * @param name - name is a file path. * * @remarks - * - The saved file path is `${GitDocumentDB#workingDir}/${name}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${name}extension`. * * - If a name parameter is undefined, it is automatically generated. * - * - _id property of a JsonDoc is automatically set or overwritten by name parameter whose .json extension is removed. + * - _id property of a JsonDoc is automatically set or overwritten by name parameter whose extension is removed. * * - An update operation is not skipped even if no change occurred on a specified data. * @@ -1144,16 +1307,18 @@ export class GitDocumentDB * @throws {@link Err.InvalidJsonFileExtensionError} * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * * @public */ @@ -1173,28 +1338,30 @@ export class GitDocumentDB * @remarks * - Throws SameIdExistsError when data that has the same _id exists. It might be better to use put() instead of insert(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${name}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${name}extension`. * * - If a name parameter is undefined, it is automatically generated. * - * - _id property of a JsonDoc is automatically set or overwritten by name parameter whose .json extension is omitted. + * - _id property of a JsonDoc is automatically set or overwritten by name parameter whose extension is omitted. * * - This is an alias of GitDocumentDB#rootCollection.insertFatDoc() * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.SameIdExistsError} (from putWorker) + * @throws - {@link Err.SameIdExistsError} * * @public */ @@ -1214,9 +1381,9 @@ export class GitDocumentDB * @remarks * - Throws DocumentNotFoundError if a specified data does not exist. It might be better to use put() instead of update(). * - * - The saved file path is `${GitDocumentDB#workingDir}/${name}.json`. + * - The saved file path is `${GitDocumentDB#workingDir}/${name}extension`. * - * - _id property of a JsonDoc is automatically set or overwritten by name parameter whose .json extension is omitted. + * - _id property of a JsonDoc is automatically set or overwritten by name parameter whose extension is omitted. * * - An update operation is not skipped even if no change occurred on a specified data. * @@ -1224,18 +1391,20 @@ export class GitDocumentDB * * @throws {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.InvalidIdCharacterError} (from validateDocument, validateId) - * @throws {@link Err.InvalidIdLengthError} (from validateDocument, validateId) + * @privateRemarks # Errors from putImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.DatabaseClosingError} (fromm putImpl) - * @throws {@link Err.TaskCancelError} (from putImpl) + * @throws # Errors from validateDocument, validateId + * @throws - {@link Err.InvalidIdCharacterError} + * @throws - {@link Err.InvalidIdLengthError} * - * @throws {@link Err.UndefinedDBError} (fromm putWorker) - * @throws {@link Err.RepositoryNotOpenError} (fromm putWorker) - * @throws {@link Err.CannotCreateDirectoryError} (from putWorker) - * @throws {@link Err.CannotWriteDataError} (from putWorker) + * @throws # Errors from putWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.CannotWriteDataError} * - * @throws {@link Err.DocumentNotFoundError} + * @throws - {@link Err.DocumentNotFoundError} * * @public */ @@ -1250,7 +1419,7 @@ export class GitDocumentDB /** * Get a JSON document * - * @param _id - _id is a file path whose .json extension is omitted. + * @param _id - _id is a file path whose extension is omitted. * * @returns * - undefined if a specified document does not exist. @@ -1260,7 +1429,6 @@ export class GitDocumentDB * - This is an alias of GitDocumentDB#rootCollection.get() * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1277,7 +1445,7 @@ export class GitDocumentDB * @returns * - undefined if a specified data does not exist. * - * - FatJsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. + * - FatJsonDoc if the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. * * - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. * @@ -1286,7 +1454,6 @@ export class GitDocumentDB * - This is an alias of GitDocumentDB#rootCollection.getFatDoc() * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1306,7 +1473,6 @@ export class GitDocumentDB * - This is an alias of GitDocumentDB#rootCollection.getDocByOid() * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1318,7 +1484,7 @@ export class GitDocumentDB /** * Get an old revision of a document * - * @param _id - _id is a file path whose .json extension is omitted. + * @param _id - _id is a file path whose extension is omitted. * @param revision - Specify a number to go back to old revision. Default is 0. * See {@link git-documentdb#GitDocumentDB.getHistory} for the array of revisions. * @param historyOptions - The array of revisions is filtered by HistoryOptions.filter. @@ -1335,7 +1501,6 @@ export class GitDocumentDB * ``` * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1359,7 +1524,7 @@ export class GitDocumentDB * @remarks * - undefined if a specified data does not exist or it is deleted. * - * - JsonDoc if the file extension is '.json'. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. + * - JsonDoc if the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. * * - FatBinaryDoc if described in .gitattribtues, otherwise FatTextDoc. * @@ -1374,7 +1539,6 @@ export class GitDocumentDB * ``` * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1396,7 +1560,7 @@ export class GitDocumentDB /** * Get revision history of a document * - * @param _id - _id is a file path whose .json extension is omitted. + * @param _id - _id is a file path whose extension is omitted. * @param historyOptions - The array of revisions is filtered by HistoryOptions.filter. * * @remarks @@ -1407,7 +1571,7 @@ export class GitDocumentDB * @returns Array of FatDoc or undefined. * - undefined if a specified document does not exist or it is deleted. * - * - JsonDoc if isJsonDocCollection is true or the file extension is '.json'. + * - JsonDoc if isJsonDocCollection is true or the file extension is SerializeFormat.extension. * * - Uint8Array or string if isJsonDocCollection is false. * @@ -1443,7 +1607,6 @@ export class GitDocumentDB * ``` * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1468,14 +1631,13 @@ export class GitDocumentDB * @returns Array of FatDoc or undefined. * - undefined if a specified data does not exist or it is deleted. * - * - Array of FatJsonDoc if isJsonDocCollection is true or the file extension is '.json'. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. + * - Array of FatJsonDoc if isJsonDocCollection is true or the file extension is SerializeFormat.extension. Be careful that JsonDoc may not have _id property when an app other than GitDocumentDB creates it. * * - Array of FatBinaryDoc if described in .gitattribtues, otherwise array of FatTextDoc. * * - getOptions.forceDocType always overwrite return type. * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1491,19 +1653,21 @@ export class GitDocumentDB /** * Delete a JSON document * - * @param _id - _id is a file path whose .json extension is omitted. + * @param _id - _id is a file path whose extension is omitted. * * @remarks * - This is an alias of GitDocumentDB#rootCollection.delete() * - * @throws {@link Err.UndefinedDocumentIdError} (from Collection#delete) - * @throws {@link Err.DatabaseClosingError} (from deleteImpl) - * @throws {@link Err.TaskCancelError} (from deleteImpl) + * @throws {@link Err.UndefinedDocumentIdError} + * + * @privateRemarks # Errors from deleteImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.RepositoryNotOpenError} (from deleteWorker) - * @throws {@link Err.UndefinedDBError} (from deleteWorker) - * @throws {@link Err.DocumentNotFoundError} (from deleteWorker) - * @throws {@link Err.CannotDeleteDataError} (from deleteWorker) + * @throws # Errors from deleteWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotDeleteDataError} * * @public */ @@ -1512,19 +1676,21 @@ export class GitDocumentDB /** * Delete a document by _id property in JsonDoc * - * @param jsonDoc - Only the _id property of the JsonDoc is referenced. _id is a file path whose .json extension is omitted. + * @param jsonDoc - Only the _id property of the JsonDoc is referenced. _id is a file path whose extension is omitted. * * @remarks * - This is an alias of GitDocumentDB#rootCollection.delete() * - * @throws {@link Err.UndefinedDocumentIdError} (from Collection#delete) - * @throws {@link Err.DatabaseClosingError} (from deleteImpl) - * @throws {@link Err.TaskCancelError} (from deleteImpl) + * @throws {@link Err.UndefinedDocumentIdError} + * + * @privateRemarks # Errors from deleteImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} * - * @throws {@link Err.RepositoryNotOpenError} (from deleteWorker) - * @throws {@link Err.UndefinedDBError} (from deleteWorker) - * @throws {@link Err.DocumentNotFoundError} (from deleteWorker) - * @throws {@link Err.CannotDeleteDataError} (from deleteWorker) + * @throws # Errors from deleteWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotDeleteDataError} * * @public */ @@ -1545,13 +1711,15 @@ export class GitDocumentDB * - This is an alias of GitDocumentDB#rootCollection.deleteFatDoc() * * @throws {@link Err.UndefinedDocumentIdError} - * @throws {@link Err.DatabaseClosingError} (from deleteImpl) - * @throws {@link Err.TaskCancelError} (from deleteImpl) * - * @throws {@link Err.RepositoryNotOpenError} (from deleteWorker) - * @throws {@link Err.UndefinedDBError} (from deleteWorker) - * @throws {@link Err.DocumentNotFoundError} (from deleteWorker) - * @throws {@link Err.CannotDeleteDataError} (from deleteWorker) + * @privateRemarks # Errors from deleteImpl + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.TaskCancelError} + * + * @throws # Errors from deleteWorker + * @throws - {@link Err.UndefinedDBError} + * @throws - {@link Err.DocumentNotFoundError} + * @throws - {@link Err.CannotDeleteDataError} * * @public */ @@ -1568,7 +1736,6 @@ export class GitDocumentDB * @param options - The options specify how to get documents. * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public @@ -1586,7 +1753,6 @@ export class GitDocumentDB * - This is an alias of GitDocumentDB#rootCollection.findFatDoc() * * @throws {@link Err.DatabaseClosingError} - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidJsonObjectError} * * @public diff --git a/src/main.ts b/src/main.ts index 733a55cd..ad613d5f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,7 +11,7 @@ export * from './error'; export * from './git_documentdb'; export * from './types'; export * from './validator'; -export * from './remote/clone'; +export * from './remote/remote_engine'; export * from './remote/remote_repository'; export * from './remote/sync'; export * from './const'; diff --git a/src/plugin/remote-isomorphic-git.ts b/src/plugin/remote-isomorphic-git.ts new file mode 100644 index 00000000..b96143bc --- /dev/null +++ b/src/plugin/remote-isomorphic-git.ts @@ -0,0 +1,531 @@ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import fs from 'fs'; +import git from 'isomorphic-git'; +import { Logger } from 'tslog'; +import { + CannotConnectError, + HTTPError401AuthorizationRequired, + HTTPError403Forbidden, + HTTPError404NotFound, + InvalidAuthenticationTypeError, + InvalidGitRemoteError, + InvalidRepositoryURLError, + InvalidURLFormatError, + NetworkError, + UnfetchedCommitExistsError, +} from 'git-documentdb-remote-errors'; +import httpClient from 'isomorphic-git/http/node'; +import { ConnectionSettingsGitHub, RemoteOptions } from '../types'; +import { NETWORK_RETRY, NETWORK_RETRY_INTERVAL } from '../const'; +import { sleep } from '../utils'; + +/** + * @public + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export const type = 'remote'; + +/** + * @public + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export const name = 'isomorphic-git'; + +/** + * Insert credential options for GitHub + * + * @throws {@link InvalidURLFormatError} + * @throws {@link InvalidRepositoryURLError} + * + * @internal + */ +function createCredentialForGitHub (options: RemoteOptions) { + if (!options.remoteUrl!.match(/^https?:\/\//)) { + throw new InvalidURLFormatError('http protocol required in createCredentialForGitHub'); + } + const connection = options.connection as ConnectionSettingsGitHub; + if (!connection.personalAccessToken) { + return undefined; + } + const urlArray = options.remoteUrl!.replace(/^https?:\/\//, '').split('/'); + // github.com/account_name/repository_name + if (urlArray.length !== 3) { + throw new InvalidRepositoryURLError(options.remoteUrl!); + } + + const credentials = + connection.personalAccessToken !== undefined + ? () => ({ username: connection.personalAccessToken }) + : undefined; + + return credentials; +} + +/** + * Create credential options + * + * @throws {@link InvalidAuthenticationTypeError} + * + * @throws # Error from createCredentialForGitHub + * @throws - {@link InvalidURLFormatError} + * @throws - {@link InvalidRepositoryURLError} + * + * @internal + */ +export function createCredentialCallback (options: RemoteOptions) { + options.connection ??= { type: 'none' }; + if (options.connection.type === 'github') { + return createCredentialForGitHub(options); + } + else if (options.connection.type === 'none') { + return undefined; + } + // @ts-ignore + throw new InvalidAuthenticationTypeError(options.connection.type); +} + +/** + * Clone + * + * @throws {@link InvalidURLFormatError} + * @throws {@link NetworkError} + * @throws {@link HTTPError401AuthorizationRequired} + * @throws {@link HTTPError404NotFound} + * @throws {@link CannotConnectError} + * + * @throws # Errors from createCredentialForGitHub + * @throws - {@link HttpProtocolRequiredError} + * @throws - {@link InvalidRepositoryURLError} + * + * @throws # Errors from createCredential + * @throws - {@link InvalidAuthenticationTypeError} + * + * @internal + */ +// eslint-disable-next-line complexity +export async function clone ( + workingDir: string, + remoteOptions: RemoteOptions, + remoteName?: string, + logger?: Logger +): Promise { + logger ??= new Logger({ + name: 'plugin-nodegit', + minLevel: 'trace', + displayDateTime: false, + displayFunctionName: false, + displayFilePath: 'hidden', + }); + logger.debug(`remote-isomorphic-git: clone: ${remoteOptions.remoteUrl}`); + + remoteName ??= 'origin'; + + remoteOptions.retry ??= NETWORK_RETRY; + remoteOptions.retryInterval ??= NETWORK_RETRY_INTERVAL; + + const cloneOption: any = { + fs, + dir: workingDir, + http: httpClient, + url: remoteOptions.remoteUrl!, + }; + const cred = createCredentialCallback(remoteOptions); + if (cred) { + cloneOption.onAuth = cred; + } + for (let i = 0; i < remoteOptions.retry! + 1; i++) { + // eslint-disable-next-line no-await-in-loop + const res = await git.clone(cloneOption).catch(err => err); + + let error = ''; + if (res instanceof Error) { + error = res.toString(); + } + else { + break; + } + + // if (error !== 'undefined') console.warn('connect fetch error: ' + error); + switch (true) { + case error.startsWith('UrlParseError:'): + case error.startsWith('Error: getaddrinfo ENOTFOUND'): + throw new InvalidURLFormatError(error); + + case error.startsWith('Error: connect EACCES'): + case error.startsWith('Error: connect ECONNREFUSED'): + // isomorphic-git throws this when network is limited. + if (i >= remoteOptions.retry!) { + throw new NetworkError(error); + } + break; + + case error.startsWith('HttpError: HTTP Error: 401'): + throw new HTTPError401AuthorizationRequired(error); + + case error.startsWith('HttpError: HTTP Error: 404 Not Found'): + throw new HTTPError404NotFound(error); + + default: + if (i >= remoteOptions.retry!) { + throw new CannotConnectError(error); + } + } + // eslint-disable-next-line no-await-in-loop + await sleep(remoteOptions.retryInterval!); + } + + // Add remote + // (default is 'origin') + if (remoteName !== 'origin') { + await git.addRemote({ + fs, + dir: workingDir, + remote: 'origin', + url: remoteOptions.remoteUrl!, + }); + } + await git.addRemote({ + fs, + dir: workingDir, + remote: remoteName, + url: remoteOptions.remoteUrl!, + }); +} + +/** + * Check connection by FETCH + * + * @throws {@link InvalidGitRemoteError} + * @throws {@link InvalidURLFormatError} + * @throws {@link NetworkError} + * @throws {@link HTTPError401AuthorizationRequired} + * @throws {@link HTTPError404NotFound} + * @throws {@link CannotConnectError} + * + * @throws # Errors from createCredentialForGitHub + * @throws - {@link HttpProtocolRequiredError} + * @throws - {@link InvalidRepositoryURLError} + * + * @throws # Errors from createCredential + * @throws - {@link InvalidAuthenticationTypeError} + * + * @internal + */ +// eslint-disable-next-line complexity +export async function checkFetch ( + workingDir: string, + remoteOptions: RemoteOptions, + remoteName?: string, + logger?: Logger +): Promise { + logger ??= new Logger({ + name: 'plugin-nodegit', + minLevel: 'trace', + displayDateTime: false, + displayFunctionName: false, + displayFilePath: 'hidden', + }); + remoteName ??= 'origin'; + + const urlOfRemote = await git.getConfig({ + fs, + dir: workingDir, + path: `remote.${remoteName}.url`, + }); + if (urlOfRemote === undefined) { + throw new InvalidGitRemoteError(`remote '${remoteName}' does not exist`); + } + + remoteOptions.retry ??= NETWORK_RETRY; + remoteOptions.retryInterval ??= NETWORK_RETRY_INTERVAL; + + const checkOption: any = { + http: httpClient, + url: remoteOptions.remoteUrl!, + }; + const cred = createCredentialCallback(remoteOptions); + if (cred) { + checkOption.onAuth = cred; + } + + for (let i = 0; i < remoteOptions.retry! + 1; i++) { + // eslint-disable-next-line no-await-in-loop + const res = await git.getRemoteInfo2(checkOption).catch(err => err); + + let error = ''; + if (res instanceof Error) { + error = res.toString(); + } + else { + break; + } + + switch (true) { + case error.startsWith('UrlParseError:'): + case error.startsWith('Error: getaddrinfo ENOTFOUND'): + throw new InvalidURLFormatError(error); + + case error.startsWith('Error: connect EACCES'): + case error.startsWith('Error: connect ECONNREFUSED'): + // isomorphic-git throws this when network is limited. + if (i >= remoteOptions.retry!) { + throw new NetworkError(error); + } + break; + + case error.startsWith('HttpError: HTTP Error: 401'): + throw new HTTPError401AuthorizationRequired(error); + + case error.startsWith('HttpError: HTTP Error: 404 Not Found'): + throw new HTTPError404NotFound(error); + + default: + if (i >= remoteOptions.retry!) { + throw new CannotConnectError(error); + } + } + // eslint-disable-next-line no-await-in-loop + await sleep(remoteOptions.retryInterval!); + } + + return true; +} + +/** + * git fetch + * + * @throws {@link InvalidGitRemoteError} + * @throws {@link InvalidURLFormatError} + * @throws {@link NetworkError} + * @throws {@link HTTPError401AuthorizationRequired} + * @throws {@link HTTPError404NotFound} + * @throws {@link CannotConnectError} + * + * @throws # Errors from createCredentialForGitHub + * @throws - {@link HttpProtocolRequiredError} + * @throws - {@link InvalidRepositoryURLError} + * + * @throws # Errors from createCredential + * @throws - {@link InvalidAuthenticationTypeError} + * + * @internal + */ +// eslint-disable-next-line complexity +export async function fetch ( + workingDir: string, + remoteOptions: RemoteOptions, + remoteName?: string, + localBranchName?: string, + remoteBranchName?: string, + logger?: Logger +): Promise { + logger ??= new Logger({ + name: 'plugin-nodegit', + minLevel: 'trace', + displayDateTime: false, + displayFunctionName: false, + displayFilePath: 'hidden', + }); + logger.debug(`remote-isomorphic-git: fetch: ${remoteOptions.remoteUrl}`); + + remoteName ??= 'origin'; + localBranchName ??= 'main'; + remoteBranchName ??= 'main'; + + const urlOfRemote = await git.getConfig({ + fs, + dir: workingDir, + path: `remote.${remoteName}.url`, + }); + if (urlOfRemote === undefined) { + throw new InvalidGitRemoteError(`remote '${remoteName}' does not exist`); + } + + remoteOptions.retry ??= NETWORK_RETRY; + remoteOptions.retryInterval ??= NETWORK_RETRY_INTERVAL; + + const fetchOption: any = { + fs, + dir: workingDir, + http: httpClient, + url: remoteOptions.remoteUrl!, + remote: remoteName, + ref: localBranchName, + remoteRef: remoteBranchName, + }; + const cred = createCredentialCallback(remoteOptions); + if (cred) { + fetchOption.onAuth = cred; + } + + for (let i = 0; i < remoteOptions.retry! + 1; i++) { + // eslint-disable-next-line no-await-in-loop + const res = await git.fetch(fetchOption).catch(err => err); + let error = ''; + if (res instanceof Error) { + error = res.toString(); + } + else { + break; + } + + // if (error !== 'undefined') console.warn('connect fetch error: ' + error); + switch (true) { + case error.startsWith('NoRefspecError'): + throw new InvalidGitRemoteError(error); + + case error.startsWith('UrlParseError:'): + case error.startsWith('Error: getaddrinfo ENOTFOUND'): + throw new InvalidURLFormatError(error); + + case error.startsWith('Error: connect EACCES'): + case error.startsWith('Error: connect ECONNREFUSED'): + // isomorphic-git throws this when network is limited. + if (i >= remoteOptions.retry!) { + throw new NetworkError(error); + } + break; + + case error.startsWith('HttpError: HTTP Error: 401'): + throw new HTTPError401AuthorizationRequired(error); + + case error.startsWith('HttpError: HTTP Error: 404 Not Found'): + throw new HTTPError404NotFound(error); + + default: + if (i >= remoteOptions.retry!) { + throw new CannotConnectError(error); + } + } + // eslint-disable-next-line no-await-in-loop + await sleep(remoteOptions.retryInterval!); + } +} + +/** + * git push + * + * @throws {@link InvalidGitRemoteError} + * @throws {@link UnfetchedCommitExistsError} + * @throws {@link InvalidURLFormatError} + * @throws {@link NetworkError} + * @throws {@link HTTPError401AuthorizationRequired} + * @throws {@link HTTPError404NotFound} + * @throws {@link HTTPError403Forbidden} + * @throws {@link CannotConnectError} + * + * @throws # Errors from createCredentialForGitHub + * @throws - {@link InvalidURLFormatError} + * @throws - {@link InvalidRepositoryURLError} + * + * @throws # Errors from createCredential + * @throws - {@link InvalidAuthenticationTypeError} + * + * @internal + */ +// eslint-disable-next-line complexity +export async function push ( + workingDir: string, + remoteOptions: RemoteOptions, + remoteName?: string, + localBranchName?: string, + remoteBranchName?: string, + logger?: Logger +): Promise { + logger ??= new Logger({ + name: 'plugin-nodegit', + minLevel: 'trace', + displayDateTime: false, + displayFunctionName: false, + displayFilePath: 'hidden', + }); + logger.debug(`remote-isomorphic-git: push: ${remoteOptions.remoteUrl}`); + + remoteName ??= 'origin'; + localBranchName ??= 'main'; + remoteBranchName ??= 'main'; + + const urlOfRemote = await git.getConfig({ + fs, + dir: workingDir, + path: `remote.${remoteName}.url`, + }); + if (urlOfRemote === undefined) { + throw new InvalidGitRemoteError(`remote '${remoteName}' does not exist`); + } + + remoteOptions.retry ??= NETWORK_RETRY; + remoteOptions.retryInterval ??= NETWORK_RETRY_INTERVAL; + + const pushOption: any = { + fs, + dir: workingDir, + http: httpClient, + url: remoteOptions.remoteUrl!, + remote: remoteName, + ref: localBranchName, + remoteRef: remoteBranchName, + }; + const cred = createCredentialCallback(remoteOptions); + if (cred) { + pushOption.onAuth = cred; + } + + for (let i = 0; i < remoteOptions.retry! + 1; i++) { + // eslint-disable-next-line no-await-in-loop + const res = await git.push(pushOption).catch(err => err); + + let error = ''; + if (res instanceof Error) { + error = res.toString(); + } + else { + break; + } + + // console.log('connect push error: ' + error); + switch (true) { + // NoRefspecError does not invoke because push does not need Remote when url is specified. + // case error.startsWith('NoRefspecError'): + // throw new InvalidGitRemoteError(error); + + case error.startsWith('PushRejectedError:'): + throw new UnfetchedCommitExistsError(); + + case error.startsWith('UrlParseError:'): + case error.startsWith('Error: getaddrinfo ENOTFOUND'): + throw new InvalidURLFormatError(error); + + case error.startsWith('Error: connect EACCES'): + case error.startsWith('Error: connect ECONNREFUSED'): + // isomorphic-git throws this when network is limited. + if (i >= remoteOptions.retry!) { + throw new NetworkError(error); + } + break; + + case error.startsWith('HttpError: HTTP Error: 401'): + throw new HTTPError401AuthorizationRequired(error); + + case error.startsWith('HttpError: HTTP Error: 404 Not Found'): + throw new HTTPError404NotFound(error); + + case error.startsWith('HttpError: HTTP Error: 403 Forbidden'): + throw new HTTPError403Forbidden(error); + + default: + if (i >= remoteOptions.retry!) { + throw new CannotConnectError(error); + } + } + // eslint-disable-next-line no-await-in-loop + await sleep(remoteOptions.retryInterval!); + } +} diff --git a/src/remote/3way_merge.ts b/src/remote/3way_merge.ts index 1cc3f528..66e576de 100644 --- a/src/remote/3way_merge.ts +++ b/src/remote/3way_merge.ts @@ -1,29 +1,29 @@ -import nodePath from 'path'; -import nodegit from '@sosuisen/nodegit'; -import git from 'isomorphic-git'; +import nodePath, { basename } from 'path'; +import git, { TreeEntry, WalkerEntry } from 'isomorphic-git'; import fs from 'fs-extra'; -import { DEFAULT_CONFLICT_RESOLUTION_STRATEGY, JSON_EXT } from '../const'; +import { DEFAULT_CONFLICT_RESOLUTION_STRATEGY } from '../const'; import { Err } from '../error'; import { AcceptedConflict, + ChangedFile, ConflictResolutionStrategies, ConflictResolutionStrategyLabels, DocType, FatDoc, IJsonPatch, JsonDoc, + SerializeFormat, } from '../types'; import { GitDDBInterface } from '../types_gitddb'; -import { - getFatDocFromData, - getFatDocFromOid, - getFatDocFromReadBlobResult, - writeBlobToFile, -} from './worker_utils'; -import { toSortedJSONString, utf8decode } from '../utils'; +import { getFatDocFromData, writeBlobToFile } from './worker_utils'; +import { utf8decode } from '../utils'; import { JsonDiff } from './json_diff'; import { SyncInterface } from '../types_sync'; +import { isSameFatDoc, textToJsonDoc } from '../crud/blob'; +/** + * @internal + */ function getStrategy ( strategy: ConflictResolutionStrategies | undefined, oursDoc?: FatDoc, @@ -48,13 +48,19 @@ function getStrategy ( return strategy; } -function getMergedDocument ( +/** + * @throws {@link Err.InvalidConflictResolutionStrategyError} + * + * @internal + */ +function getMergedJsonDoc ( jsonDiff: JsonDiff, jsonPatch: IJsonPatch, strategy: ConflictResolutionStrategyLabels, base: JsonDoc | undefined, ours: JsonDoc, - theirs: JsonDoc + theirs: JsonDoc, + serializeFormat: SerializeFormat ): string { let result: { [key: string]: string }; if (strategy === 'ours') { @@ -82,66 +88,290 @@ function getMergedDocument ( ); } else { - result = {}; + throw new Err.InvalidConflictResolutionStrategyError(); + } + return serializeFormat.serialize(result).data; +} + +/** + * @throws {@link Err.InvalidConflictResolutionStrategyError} + * + * @internal + */ +function getMergedTextDoc ( + strategy: ConflictResolutionStrategyLabels, + base: string | undefined, + ours: string, + theirs: string +): string { + if (strategy === 'ours') { + return ours; + } + else if (strategy === 'theirs') { + return theirs; + } + else if (strategy === 'ours-diff') { + // TODO: implement diff and patch + return ours; + } + else if (strategy === 'theirs-diff') { + // TODO: implement diff and patch + return theirs; + } + + throw new Err.InvalidConflictResolutionStrategyError(); +} + +/** + * @throws {@link Err.InvalidConflictResolutionStrategyError} + * + * @internal + */ +function getMergedBinaryDoc ( + strategy: ConflictResolutionStrategyLabels, + ours: Uint8Array, + theirs: Uint8Array +): Uint8Array { + if (strategy === 'ours') { + return ours; + } + else if (strategy === 'theirs') { + return theirs; + } + + throw new Err.InvalidConflictResolutionStrategyError(); +} + +/** + * getMergedDocument + * + * @throws {@link Err.InvalidDocTypeError} + * + * @throws # Errors from getMergedJsonDoc, getMergedTextDoc, getMergedBinaryDoc + * @throws - {@link Err.InvalidConflictResolutionStrategyError} + * + * @internal + */ +function getMergedDocument ( + jsonDiff: JsonDiff, + jsonPatch: IJsonPatch, + strategy: ConflictResolutionStrategyLabels, + base: Uint8Array | undefined, + ours: Uint8Array, + theirs: Uint8Array, + docType: DocType, + serializeFormat: SerializeFormat, + extension = '' +): string | Uint8Array { + if (docType === 'json') { + const oursDoc = textToJsonDoc(utf8decode(ours), serializeFormat, extension); + const theirsDoc = textToJsonDoc(utf8decode(theirs), serializeFormat, extension); + let baseDoc: JsonDoc | undefined; + if (base) { + baseDoc = textToJsonDoc(utf8decode(base), serializeFormat, extension); + } + else { + baseDoc = undefined; + } + return getMergedJsonDoc( + jsonDiff, + jsonPatch, + strategy, + baseDoc, + oursDoc, + theirsDoc, + serializeFormat + ); + } + else if (docType === 'text') { + const oursDoc = utf8decode(ours); + const theirsDoc = utf8decode(theirs); + let baseDoc: string | undefined; + if (base) { + baseDoc = utf8decode(base); + } + else { + baseDoc = undefined; + } + return getMergedTextDoc(strategy, baseDoc, oursDoc, theirsDoc); } - return toSortedJSONString(result); + else if (docType === 'binary') { + return getMergedBinaryDoc(strategy, ours, theirs); + } + + throw new Err.InvalidDocTypeError(docType); +} + +/** + * merge + * + * @throws Errors from {@link threeWayMerge} + * + * @internal + */ +export async function merge ( + gitDDB: GitDDBInterface, + sync: SyncInterface, + baseCommitOid: string, + oursCommitOid: string, + theirsCommitOid: string +): Promise<[string, ChangedFile[], ChangedFile[], AcceptedConflict[]]> { + const acceptedConflicts: AcceptedConflict[] = []; + const localChanges: ChangedFile[] = []; + const remoteChanges: ChangedFile[] = []; + + const strategy = sync.options.conflictResolutionStrategy!; + const results = await git.walk({ + fs, + dir: gitDDB.workingDir, + trees: [ + git.TREE({ ref: baseCommitOid }), + git.TREE({ ref: oursCommitOid }), + git.TREE({ ref: theirsCommitOid }), + ], + // @ts-ignore + // eslint-disable-next-line complexity + map: async function (fullDocPath, [base, ours, theirs]) { + const baseType = base === null ? undefined : await base.type(); + if (baseType === 'tree') { + return { + mode: (await base!.mode()).toString(8), + path: basename(fullDocPath), + oid: await base!.oid(), + type: await base!.type(), + }; + } + + const oursType = ours === null ? undefined : await ours.type(); + if (oursType === 'tree') { + return { + mode: (await ours!.mode()).toString(8), + path: basename(fullDocPath), + oid: await ours!.oid(), + type: await ours!.type(), + }; + } + + const theirsType = theirs === null ? undefined : await theirs.type(); + if (theirsType === 'tree') { + return { + mode: (await theirs!.mode()).toString(8), + path: basename(fullDocPath), + oid: await theirs!.oid(), + type: await theirs!.type(), + }; + } + + const [treeEntry, localChange, remoteChange, conflict] = await threeWayMerge( + gitDDB, + sync, + strategy, + fullDocPath, + base, + ours, + theirs + ); + + if (localChange !== undefined) { + localChanges.push(localChange); + } + if (remoteChange !== undefined) { + remoteChanges.push(remoteChange); + } + if (conflict !== undefined) { + acceptedConflicts.push(conflict); + } + + if (treeEntry === undefined) { + return; + } + return treeEntry; + }, + reduce: async (parent, children) => { + if (!parent) return; + + if (parent.type === 'tree') { + if (children.length === 0) return; + + const newTreeOid = await git.writeTree({ + fs, + dir: gitDDB.workingDir, + tree: children, + }); + // eslint-disable-next-line require-atomic-updates + parent.oid = newTreeOid; + } + return parent; + }, + }); + + const mergedTreeOid = results.oid; + + // Entries in walk are traversed in alphabetical order + // (https://isomorphic-git.org/docs/en/walk), + // but sometimes the order collapse. + + // eslint-disable-next-line complexity + const sortChangedFile = (a: ChangedFile, b: ChangedFile) => { + if (a.operation === 'insert' && b.operation === 'insert') { + if (a.new.name > b.new.name) return 1; + if (a.new.name < b.new.name) return -1; + return 0; + } + else if ( + (a.operation === 'update' || a.operation === 'delete') && + (b.operation === 'update' || b.operation === 'delete') + ) { + if (a.old.name > b.old.name) return 1; + if (a.old.name < b.old.name) return -1; + return 0; + } + // This line must not be reached. + return 0; + }; + localChanges.sort(sortChangedFile); + remoteChanges.sort(sortChangedFile); + + return [mergedTreeOid, localChanges, remoteChanges, acceptedConflicts]; } /** * 3-way merge * - * @throws {@link Err.RepositoryNotOpenError} * @throws {@link Err.InvalidConflictStateError} * @throws {@link Err.CannotDeleteDataError} - * @throws {@link Err.CannotCreateDirectoryError} (from writeBlobToFile) - * @throws {@link Err.InvalidJsonObjectError} (from getFatDocFromData, getFatDocFromReadBlobResult) + * + * @throws # Errors from getMergedDocument + * @throws - {@link Err.InvalidDocTypeError} + * @throws - {@link Err.InvalidConflictResolutionStrategyError} + * + * @throws # Errors from writeBlobToFile + * @throws - {@link Err.CannotCreateDirectoryError} + * + * @throws # Errors from getFatDocFromData, getFatDocFromReadBlobResult + * @throws - {@link Err.InvalidJsonObjectError} + * */ // eslint-disable-next-line complexity export async function threeWayMerge ( gitDDB: GitDDBInterface, sync: SyncInterface, conflictResolutionStrategy: ConflictResolutionStrategies, - resolvedIndex: nodegit.Index, fullDocPath: string, - mergeBaseOid: string, - oursCommitOid: string, - theirsCommitOid: string, - acceptedConflicts: AcceptedConflict[] -): Promise { - const repos = gitDDB.repository(); - if (repos === undefined) { - throw new Err.RepositoryNotOpenError(); - } - // Try 3-way merge on the assumption that their is no conflict. - const base = await git - .readBlob({ - fs, - dir: gitDDB.workingDir, - oid: mergeBaseOid, - filepath: fullDocPath, - }) - .catch(() => undefined); - - const ours = await git - .readBlob({ - fs, - dir: gitDDB.workingDir, - oid: oursCommitOid, - filepath: fullDocPath, - }) - .catch(() => undefined); - - const theirs = await git - .readBlob({ - fs, - dir: gitDDB.workingDir, - oid: theirsCommitOid, - filepath: fullDocPath, - }) - .catch(() => undefined); - - const _id = fullDocPath.replace(new RegExp(JSON_EXT + '$'), ''); - const docType: DocType = fullDocPath.endsWith('.json') ? 'json' : 'text'; + base: WalkerEntry | null, + ours: WalkerEntry | null, + theirs: WalkerEntry | null +): Promise< + [ + TreeEntry | undefined, + ChangedFile | undefined, + ChangedFile | undefined, + AcceptedConflict | undefined + ] +> { + const docType: DocType = gitDDB.serializeFormat.hasObjectExtension(fullDocPath) + ? 'json' + : 'text'; if (docType === 'text') { // TODO: select binary or text by .gitattribtues } @@ -154,274 +384,598 @@ export async function threeWayMerge ( ); } else if (!base && !ours && theirs) { - // A new file has been inserted on theirs. - // Write it to the file. - // console.log(' #case 1 - Accept theirs (insert): ' + path); - await writeBlobToFile(gitDDB, fullDocPath, utf8decode(theirs!.blob)); - await resolvedIndex.addByPath(fullDocPath); + // A new file has been inserted into theirs. + // Write it to the working directory. + // Write it to the index. + // console.log(' #case 1 - Accept theirs (insert): ' + fullDocPath); + const theirsData = (await theirs.content())!; + const theirsFatDoc = await getFatDocFromData( + theirsData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + await writeBlobToFile(gitDDB.workingDir, fullDocPath, theirsData); + await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + return [ + { + mode: (await theirs.mode()).toString(8), + path: basename(fullDocPath), + oid: await theirs.oid(), + type: 'blob', + }, + { + operation: 'insert', + new: theirsFatDoc, + }, + undefined, + undefined, + ]; } else if (!base && ours && !theirs) { - // A new file has been inserted on ours. - // Just add it to the index. - // console.log(' #case 2 - Accept ours (insert): ' + path); - await resolvedIndex.addByPath(fullDocPath); + // A new file has been inserted into ours. + // It has already been created on the working directory. + // It has already been added to the index. + // console.log(' #case 2 - Accept ours (insert): ' + fullDocPath); + const oursData = (await ours.content())!; + const oursFatDoc = await getFatDocFromData( + oursData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + return [ + { + mode: (await ours.mode()).toString(8), + path: basename(fullDocPath), + oid: await ours.oid(), + type: 'blob', + }, + undefined, + { + operation: 'insert', + new: oursFatDoc, + }, + undefined, + ]; } else if (!base && ours && theirs) { - if (ours.oid === theirs.oid) { + const oursOid = await ours.oid(); + const theirsOid = await theirs.oid(); + + const oursMode = (await ours.mode()).toString(8); + const theirsMode = (await theirs.mode()).toString(8); + + if (oursOid === theirsOid && oursMode === theirsMode) { // The same filenames with exactly the same contents are inserted on both local and remote. - // console.log(' #case 3 - Accept both (insert): ' + path); - // Jut add it to the index. - await resolvedIndex.addByPath(fullDocPath); + // It has already been created on the both working directory. + // It has already been added to the both index. + // console.log(' #case 3 - Accept both (insert): ' + fullDocPath); + return [ + { + mode: oursMode, + path: basename(fullDocPath), + oid: oursOid, + type: 'blob', + }, + undefined, + undefined, + undefined, + ]; + } + + // ! Conflict + const oursData = (await ours.content())!; + const theirsData = (await theirs.content())!; + const oursFatDoc = await getFatDocFromData( + oursData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + const theirsFatDoc = await getFatDocFromData( + theirsData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + + const strategy = await getStrategy( + conflictResolutionStrategy, + oursFatDoc, + theirsFatDoc + ); + + let mode = ''; + if (strategy === 'ours' || strategy === 'ours-diff') { + // console.log(' #case 4 - Conflict. Accept ours (insert): ' + fullDocPath); + mode = oursMode; + } + else if (strategy === 'theirs' || strategy === 'theirs-diff') { + // console.log(' #case 5 - Conflict. Accept theirs (insert): ' + fullDocPath); + mode = theirsMode; + } + + let resultFatDoc: FatDoc; + let localChange: ChangedFile | undefined; + let remoteChange: ChangedFile | undefined; + if (strategy === 'ours') { + // Can skip getMergedDocument(). + resultFatDoc = oursFatDoc; + + localChange = undefined; + remoteChange = { + operation: 'update', + old: theirsFatDoc, + new: oursFatDoc, + }; + } + else if (strategy === 'theirs') { + // Can skip getMergedDocument(). + resultFatDoc = theirsFatDoc; + await writeBlobToFile(gitDDB.workingDir, fullDocPath, theirsData); + await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + localChange = { + operation: 'update', + old: oursFatDoc, + new: theirsFatDoc, + }; + remoteChange = undefined; } else { - // ! Conflict - const strategy = await getStrategy( - conflictResolutionStrategy, - getFatDocFromReadBlobResult(fullDocPath, ours, docType), - getFatDocFromReadBlobResult(fullDocPath, theirs, docType) + // Diff and patch + const extensionMatch = fullDocPath.match(/.+(\..+?)$/); + let extension = ''; + if (extensionMatch) { + extension = extensionMatch[1]; + } + const data = await getMergedDocument( + sync.jsonDiff, + sync.jsonPatch, + strategy, + undefined, + oursData, + theirsData, + docType, + gitDDB.serializeFormat, + extension ); - if (strategy === 'ours' || strategy === 'ours-diff') { - // Just add it to the index. - // console.log(' #case 4 - Conflict. Accept ours (insert): ' + path); - const data = await getMergedDocument( - sync.jsonDiff, - sync.jsonPatch, - strategy, - undefined, - JSON.parse(utf8decode(ours!.blob)), - JSON.parse(utf8decode(theirs!.blob)) - ); - - await writeBlobToFile(gitDDB, fullDocPath, data); - - await resolvedIndex.addByPath(fullDocPath); - - const fatDoc: FatDoc = await getFatDocFromData(data, fullDocPath, docType); - - acceptedConflicts.push({ - fatDoc, - strategy: strategy, - operation: strategy === 'ours' ? 'insert' : 'insert-merge', - }); + resultFatDoc = await getFatDocFromData( + data, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + await writeBlobToFile(gitDDB.workingDir, fullDocPath, data); + await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + + if (!isSameFatDoc(oursFatDoc, resultFatDoc)) { + localChange = { + operation: 'update', + old: oursFatDoc, + new: resultFatDoc, + }; } - else if (strategy === 'theirs' || strategy === 'theirs-diff') { - // Write theirs to the file. - // console.log(' #case 5 - Conflict. Accept theirs (insert): ' + path); - const data = await getMergedDocument( - sync.jsonDiff, - sync.jsonPatch, - strategy, - undefined, - JSON.parse(utf8decode(ours!.blob)), - JSON.parse(utf8decode(theirs!.blob)) - ); - await writeBlobToFile(gitDDB, fullDocPath, data); - - await resolvedIndex.addByPath(fullDocPath); - - const fatDoc: FatDoc = await getFatDocFromData(data, fullDocPath, docType); - - acceptedConflicts.push({ - fatDoc, - strategy: strategy, - operation: strategy === 'theirs' ? 'insert' : 'insert-merge', - }); + if (!isSameFatDoc(theirsFatDoc, resultFatDoc)) { + remoteChange = { + operation: 'update', + old: theirsFatDoc, + new: resultFatDoc, + }; } } + + const acceptedConflict: AcceptedConflict = { + fatDoc: resultFatDoc, + strategy, + operation: strategy.endsWith('-diff') ? 'insert-merge' : 'insert', + }; + + return [ + { + mode, + path: basename(fullDocPath), + oid: resultFatDoc.fileOid, + type: 'blob', + }, + localChange, + remoteChange, + acceptedConflict, + ]; } else if (base && !ours && !theirs) { - // The same files are removed. - // console.log(' #case 6 - Accept both (delete): ' + path); - await resolvedIndex.removeByPath(fullDocPath); + // The same files have been removed from both local and remote. + // console.log(' #case 6 - Accept both (delete): ' + fullDocPath); + return [undefined, undefined, undefined, undefined]; } else if (base && !ours && theirs) { - if (base.oid === theirs.oid) { - // A file has been removed on ours. - // console.log(' #case 7 - Accept ours (delete): ' + path); - await resolvedIndex.removeByPath(fullDocPath); - } - else { - // ! Conflict - const strategy = await getStrategy( - conflictResolutionStrategy, + const baseOid = await base.oid(); + const theirsOid = await theirs.oid(); + const theirsData = (await theirs.content())!; + const theirsFatDoc = await getFatDocFromData( + theirsData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + + if (baseOid === theirsOid) { + // A file has been removed from ours. + // console.log(' #case 7 - Accept ours (delete): ' + fullDocPath); + return [ undefined, - getFatDocFromReadBlobResult(fullDocPath, theirs, docType) - ); - if (strategy === 'ours' || strategy === 'ours-diff') { - // Just add it to the index. - // console.log(' #case 8 - Conflict. Accept ours (delete): ' + path); - const fatDoc: FatDoc = await getFatDocFromOid( - gitDDB.workingDir, - fullDocPath, - base.oid, - docType - ); - - acceptedConflicts.push({ - fatDoc, - strategy: strategy, + undefined, + { operation: 'delete', - }); - await resolvedIndex.removeByPath(fullDocPath); - } - else if (strategy === 'theirs' || strategy === 'theirs-diff') { - // Write theirs to the file. - // console.log(' #case 9 - Conflict. Accept theirs (update): ' + path); - const fatDoc: FatDoc = await getFatDocFromOid( - gitDDB.workingDir, - fullDocPath, - theirs.oid, - docType - ); - - acceptedConflicts.push({ - fatDoc, - strategy: strategy, - operation: 'update', - }); + old: theirsFatDoc, + }, + undefined, + ]; + } - const data = utf8decode(theirs!.blob); + // ! Conflict - await writeBlobToFile(gitDDB, fullDocPath, data); + const strategy = await getStrategy(conflictResolutionStrategy, undefined, theirsFatDoc); - await resolvedIndex.addByPath(fullDocPath); - } + if (strategy === 'ours' || strategy === 'ours-diff') { + // console.log(' #case 8 - Conflict. Accept ours (delete): ' + fullDocPath); + const baseData = (await base.content())!; + const baseFatDoc = await getFatDocFromData( + baseData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + const acceptedConflict: AcceptedConflict = { + fatDoc: baseFatDoc, + strategy: strategy, + operation: 'delete', + }; + return [ + undefined, + undefined, + { + operation: 'delete', + old: theirsFatDoc, + }, + acceptedConflict, + ]; + } + else if (strategy === 'theirs' || strategy === 'theirs-diff') { + // console.log(' #case 9 - Conflict. Accept theirs (update): ' + fullDocPath); + const acceptedConflict: AcceptedConflict = { + fatDoc: theirsFatDoc, + strategy: strategy, + operation: 'update', + }; + await writeBlobToFile(gitDDB.workingDir, fullDocPath, theirsData); + await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + return [ + { + mode: (await theirs.mode()).toString(8), + path: basename(fullDocPath), + oid: theirsFatDoc.fileOid, + type: 'blob', + }, + { + operation: 'insert', + new: theirsFatDoc, + }, + undefined, + acceptedConflict, + ]; } } else if (base && ours && !theirs) { - if (base.oid === ours.oid) { - // A file has been removed on theirs. - // console.log(' #case 10 - Accept theirs (delete): ' + path); - await fs.remove(nodePath.resolve(repos.workdir(), fullDocPath)).catch(() => { + const baseOid = await base.oid(); + const oursOid = await ours.oid(); + const oursData = (await ours.content())!; + const oursFatDoc = await getFatDocFromData( + oursData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + + if (baseOid === oursOid) { + // A file has been removed from theirs. + // console.log(' #case 10 - Accept theirs (delete): ' + fullDocPath); + await fs.remove(nodePath.resolve(gitDDB.workingDir, fullDocPath)).catch(() => { throw new Err.CannotDeleteDataError(); }); - await resolvedIndex.removeByPath(fullDocPath); + await git.remove({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + return [ + undefined, + { + operation: 'delete', + old: oursFatDoc, + }, + undefined, + undefined, + ]; } - else { - // ! Conflict - const strategy = await getStrategy( - conflictResolutionStrategy, - getFatDocFromReadBlobResult(fullDocPath, ours, docType), - undefined - ); - if (strategy === 'ours' || strategy === 'ours-diff') { - // Just add to the index. - // console.log(' #case 11 - Conflict. Accept ours (update): ' + path); - const fatDoc: FatDoc = await getFatDocFromOid( - gitDDB.workingDir, - fullDocPath, - ours.oid, - docType - ); - - acceptedConflicts.push({ - fatDoc, - strategy: strategy, - operation: 'update', - }); - const data = utf8decode(ours!.blob); - - await writeBlobToFile(gitDDB, fullDocPath, data); - - await resolvedIndex.addByPath(fullDocPath); - } - else if (strategy === 'theirs' || strategy === 'theirs-diff') { - // Remove file - // console.log(' #case 12 - Conflict. Accept theirs (delete): ' + path); - const fatDoc: FatDoc = await getFatDocFromOid( - gitDDB.workingDir, - fullDocPath, - base.oid, - docType - ); - - acceptedConflicts.push({ - fatDoc, - strategy: strategy, + // ! Conflict + + const strategy = await getStrategy(conflictResolutionStrategy, oursFatDoc, undefined); + + if (strategy === 'ours' || strategy === 'ours-diff') { + // console.log(' #case 11 - Conflict. Accept ours (update): ' + fullDocPath); + const acceptedConflict: AcceptedConflict = { + fatDoc: oursFatDoc, + strategy: strategy, + operation: 'update', + }; + return [ + { + mode: (await ours.mode()).toString(8), + path: basename(fullDocPath), + oid: oursOid, + type: 'blob', + }, + undefined, + { + operation: 'insert', + new: oursFatDoc, + }, + acceptedConflict, + ]; + } + else if (strategy === 'theirs' || strategy === 'theirs-diff') { + // console.log(' #case 12 - Conflict. Accept theirs (delete): ' + fullDocPath); + const baseData = (await base.content())!; + const baseFatDoc = await getFatDocFromData( + baseData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + const acceptedConflicts: AcceptedConflict = { + fatDoc: baseFatDoc, + strategy: strategy, + operation: 'delete', + }; + await fs.remove(nodePath.resolve(gitDDB.workingDir, fullDocPath)).catch(() => { + throw new Err.CannotDeleteDataError(); + }); + await git.remove({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + return [ + undefined, + { operation: 'delete', - }); - await fs.remove(nodePath.resolve(repos.workdir(), fullDocPath)).catch(() => { - throw new Err.CannotDeleteDataError(); - }); - await resolvedIndex.removeByPath(fullDocPath); - } + old: oursFatDoc, + }, + undefined, + acceptedConflicts, + ]; } } else if (base && ours && theirs) { - if (ours.oid === theirs.oid) { - // The same filenames with exactly the same contents are inserted on both local and remote. - // Jut add it to the index. - // console.log(' #case 13 - Accept both (update): ' + path); - await resolvedIndex.addByPath(fullDocPath); - } - else if (base.oid === ours.oid) { - // Write theirs to the file. - // console.log(' #case 14 - Accept theirs (update): ' + path); - const data = utf8decode(theirs!.blob); - await writeBlobToFile(gitDDB, fullDocPath, data); - await resolvedIndex.addByPath(fullDocPath); + const baseOid = await base.oid(); + const oursOid = await ours.oid(); + const theirsOid = await theirs.oid(); + + if (oursOid === theirsOid) { + // The same filenames with exactly the same contents are inserted into both local and remote. + // console.log(' #case 13 - Accept both (update): ' + fullDocPath); + return [ + { + // TODO: check whether mode is the same. + mode: (await ours.mode()).toString(8), + path: basename(fullDocPath), + oid: oursOid, + type: 'blob', + }, + undefined, + undefined, + undefined, + ]; } - else if (base.oid === theirs.oid) { - // Jut add it to the index. - // console.log(' #case 15 - Accept ours (update): ' + path); - await resolvedIndex.addByPath(fullDocPath); + else if (baseOid === oursOid) { + // console.log(' #case 14 - Accept theirs (update): ' + fullDocPath); + const oursData = (await ours.content())!; + const oursFatDoc = await getFatDocFromData( + oursData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + const theirsData = (await theirs.content())!; + const theirsFatDoc = await getFatDocFromData( + theirsData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + await writeBlobToFile(gitDDB.workingDir, fullDocPath, theirsData); + await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + return [ + { + mode: (await theirs.mode()).toString(8), + path: basename(fullDocPath), + oid: theirsFatDoc.fileOid, + type: 'blob', + }, + { + operation: 'update', + old: oursFatDoc, + new: theirsFatDoc, + }, + undefined, + undefined, + ]; } - else { - // ! Conflict - const strategy = await getStrategy( - conflictResolutionStrategy, - getFatDocFromReadBlobResult(fullDocPath, ours, docType), - getFatDocFromReadBlobResult(fullDocPath, theirs, docType) + else if (baseOid === theirsOid) { + // console.log(' #case 15 - Accept ours (update): ' + fullDocPath); + const oursData = (await ours.content())!; + const oursFatDoc = await getFatDocFromData( + oursData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + const theirsData = (await theirs.content())!; + const theirsFatDoc = await getFatDocFromData( + theirsData, + fullDocPath, + docType, + gitDDB.serializeFormat ); - if (strategy === 'ours' || strategy === 'ours-diff') { - // Just add it to the index. - // console.log(' #case 16 - Conflict. Accept ours (update): ' + path); - const data = await getMergedDocument( - sync.jsonDiff, - sync.jsonPatch, - strategy, - JSON.parse(utf8decode(base!.blob)), - JSON.parse(utf8decode(ours!.blob)), - JSON.parse(utf8decode(theirs!.blob)) - ); - - await writeBlobToFile(gitDDB, fullDocPath, data); - - await resolvedIndex.addByPath(fullDocPath); - - const fatDoc: FatDoc = await getFatDocFromData(data, fullDocPath, docType); - - acceptedConflicts.push({ - fatDoc, + return [ + { + mode: (await theirs.mode()).toString(8), + path: basename(fullDocPath), + oid: oursFatDoc.fileOid, + type: 'blob', + }, + undefined, + { + operation: 'update', + old: theirsFatDoc, + new: oursFatDoc, + }, + undefined, + ]; + } + + // ! Conflict + + const baseData = (await base.content())!; + const oursData = (await ours.content())!; + const theirsData = (await theirs.content())!; + const oursFatDoc = await getFatDocFromData( + oursData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + const theirsFatDoc = await getFatDocFromData( + theirsData, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + const strategy = await getStrategy( + conflictResolutionStrategy, + oursFatDoc, + theirsFatDoc + ); + + if (strategy === 'ours') { + // console.log(' #case 16 - Conflict. Accept ours (update): ' + fullDocPath); + return [ + { + mode: (await ours.mode()).toString(8), + path: basename(fullDocPath), + oid: oursFatDoc.fileOid, + type: 'blob', + }, + undefined, + { + operation: 'update', + old: theirsFatDoc, + new: oursFatDoc, + }, + { + fatDoc: oursFatDoc, strategy: strategy, - operation: strategy === 'ours' ? 'update' : 'update-merge', - }); - } - else if (strategy === 'theirs' || strategy === 'theirs-diff') { - // Write theirs to the file. - // console.log(' #case 17 - Conflict. Accept theirs (update): ' + path); - const data = await getMergedDocument( - sync.jsonDiff, - sync.jsonPatch, - strategy, - JSON.parse(utf8decode(base!.blob)), - JSON.parse(utf8decode(ours!.blob)), - JSON.parse(utf8decode(theirs!.blob)) - ); - - await writeBlobToFile(gitDDB, fullDocPath, data); - - await resolvedIndex.addByPath(fullDocPath); - - const fatDoc: FatDoc = await getFatDocFromData(data, fullDocPath, docType); - - acceptedConflicts.push({ - fatDoc, + operation: 'update', + }, + ]; + } + else if (strategy === 'theirs') { + // console.log(' #case 17 - Conflict. Accept theirs (update): ' + fullDocPath); + await writeBlobToFile(gitDDB.workingDir, fullDocPath, theirsData); + await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + + return [ + { + mode: (await theirs.mode()).toString(8), + path: basename(fullDocPath), + oid: theirsFatDoc.fileOid, + type: 'blob', + }, + { + operation: 'update', + old: oursFatDoc, + new: theirsFatDoc, + }, + undefined, + { + fatDoc: theirsFatDoc, strategy: strategy, - operation: strategy === 'theirs' ? 'update' : 'update-merge', - }); - } + operation: 'update', + }, + ]; + } + + const extensionMatch = fullDocPath.match(/.+(\..+?)$/); + let extension = ''; + if (extensionMatch) { + extension = extensionMatch[1]; } + const data = await getMergedDocument( + sync.jsonDiff, + sync.jsonPatch, + strategy, + baseData, + oursData, + theirsData, + docType, + gitDDB.serializeFormat, + extension + ); + const resultFatDoc = await getFatDocFromData( + data, + fullDocPath, + docType, + gitDDB.serializeFormat + ); + await writeBlobToFile(gitDDB.workingDir, fullDocPath, data); + await git.add({ fs, dir: gitDDB.workingDir, filepath: fullDocPath }); + + let mode = ''; + if (strategy === 'ours-diff') { + // console.log(' #case 16 (diff) - Conflict. Accept ours (update): ' + fullDocPath); + mode = (await ours.mode()).toString(8); + } + else if (strategy === 'theirs-diff') { + // console.log(' #case 17 (diff) - Conflict. Accept theirs (update): ' + fullDocPath); + mode = (await theirs.mode()).toString(8); + } + + let localChange: ChangedFile | undefined; + let remoteChange: ChangedFile | undefined; + if (!isSameFatDoc(oursFatDoc, resultFatDoc)) { + localChange = { + operation: 'update', + old: oursFatDoc, + new: resultFatDoc, + }; + } + if (!isSameFatDoc(theirsFatDoc, resultFatDoc)) { + remoteChange = { + operation: 'update', + old: theirsFatDoc, + new: resultFatDoc, + }; + } + + return [ + { + mode, + path: basename(fullDocPath), + oid: resultFatDoc.fileOid, + type: 'blob', + }, + localChange, + remoteChange, + { + fatDoc: resultFatDoc, + strategy: strategy, + operation: 'update-merge', + }, + ]; } + throw new Err.InvalidConflictStateError('Invalid case'); } diff --git a/src/remote/authentication.ts b/src/remote/authentication.ts deleted file mode 100644 index 5b0338ae..00000000 --- a/src/remote/authentication.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -import nodegit from '@sosuisen/nodegit'; -import { Err } from '../error'; -import { ConnectionSettingsGitHub, ConnectionSettingsSSH, RemoteOptions } from '../types'; - -/** - * Insert credential options for GitHub - * - * @internal - */ -function createCredentialForGitHub (options: RemoteOptions) { - if (!options.remoteUrl!.match(/^https?:\/\//)) { - throw new Err.HttpProtocolRequiredError(options.remoteUrl!); - } - const connection = options.connection as ConnectionSettingsGitHub; - if (options.syncDirection !== 'pull' && !connection.personalAccessToken) { - throw new Err.UndefinedPersonalAccessTokenError(); - } - const urlArray = options.remoteUrl!.replace(/^https?:\/\//, '').split('/'); - // github.com/account_name/repository_name - if (urlArray.length !== 3) { - throw new Err.InvalidRepositoryURLError(options.remoteUrl!); - } - const owner = urlArray[urlArray.length - 2]; - const credentials = () => { - return nodegit.Cred.userpassPlaintextNew(owner, connection.personalAccessToken!); - }; - return credentials; -} - -/** - * Create credential options for SSH - * - * @internal - */ -function createCredentialForSSH (options: RemoteOptions) { - const connection = options.connection as ConnectionSettingsSSH; - if (connection.privateKeyPath === undefined || connection.privateKeyPath === '') { - throw new Err.InvalidSSHKeyPathError(); - } - if (connection.publicKeyPath === undefined || connection.publicKeyPath === '') { - throw new Err.InvalidSSHKeyPathError(); - } - connection.passPhrase ??= ''; - - const credentials = (url: string, userName: string) => { - return nodegit.Cred.sshKeyNew( - userName, - connection.publicKeyPath, - connection.privateKeyPath, - connection.passPhrase! - ); - }; - return credentials; -} - -/** - * Create credential options - * - * @internal - */ -export function createCredential (options: RemoteOptions) { - options.connection ??= { type: 'none' }; - let cred: any; - if (options.connection.type === 'github') { - cred = createCredentialForGitHub(options); - } - else if (options.connection.type === 'ssh') { - cred = createCredentialForSSH(options); - } - else if (options.connection.type === 'none') { - // nop - } - else { - // @ts-ignore - throw new Err.InvalidAuthenticationTypeError(options.connection.type); - } - - const callbacks = { - credentials: cred, - }; - - if (process.platform === 'darwin') { - // @ts-ignore - callbacks.certificateCheck = () => 0; - } - return callbacks; -} diff --git a/src/remote/clone.ts b/src/remote/clone.ts deleted file mode 100644 index 8f6b0dc4..00000000 --- a/src/remote/clone.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -import nodegit from '@sosuisen/nodegit'; -import { Logger } from 'tslog'; -import { Err } from '../error'; -import { sleep } from '../utils'; -import { NETWORK_RETRY, NETWORK_RETRY_INTERVAL, NETWORK_TIMEOUT } from '../const'; -import { RemoteOptions } from '../types'; -import { createCredential } from './authentication'; -import { checkHTTP } from './net'; - -/** - * Clone repository from remote - * - * @throws {@link Err.CannotConnectError} - * - * @internal - */ -export async function cloneRepository ( - workingDir: string, - remoteOptions: RemoteOptions, - logger?: Logger -) { - logger ??= new Logger({ - name: 'clone', - minLevel: 'trace', - displayDateTime: false, - displayFunctionName: false, - displayFilePath: 'hidden', - }); - if ( - remoteOptions !== undefined && - remoteOptions.remoteUrl !== undefined && - remoteOptions.remoteUrl !== '' - ) { - /** - * Retry if network errors. - */ - let result: { - ok: boolean; - code?: number; - error?: Error; - } = { - ok: false, - }; - let retry = 0; - for (; retry < NETWORK_RETRY; retry++) { - // eslint-disable-next-line no-await-in-loop - result = await checkHTTP(remoteOptions.remoteUrl!, NETWORK_TIMEOUT).catch(err => err); - if (result.ok) { - break; - } - else { - logger.debug(`NetworkError in cloning: ${remoteOptions.remoteUrl}, ` + result); - } - // eslint-disable-next-line no-await-in-loop - await sleep(NETWORK_RETRY_INTERVAL); - } - if (!result.ok) { - // Set retry number for code test - throw new Err.CannotConnectError(retry, remoteOptions.remoteUrl, result.toString()); - } - - return await nodegit.Clone.clone(remoteOptions.remoteUrl, workingDir, { - fetchOpts: { - callbacks: createCredential(remoteOptions), - }, - }).catch(err => { - // Errors except CannotConnectError are handled in sync(). - logger!.debug(`Error in cloning: ${remoteOptions.remoteUrl}, ` + err); - // The db will try to create remote repository in sync() if 'undefined' is returned. - return undefined; - }); - } - - return undefined; -} diff --git a/src/remote/combine.ts b/src/remote/combine.ts index 5df33284..cee82b16 100644 --- a/src/remote/combine.ts +++ b/src/remote/combine.ts @@ -8,51 +8,98 @@ */ import path from 'path'; import git from 'isomorphic-git'; -import nodegit from '@sosuisen/nodegit'; import fs from 'fs-extra'; import { ulid } from 'ulid'; import rimraf from 'rimraf'; -import { cloneRepository } from './clone'; +import { textToJsonDoc } from '../crud/blob'; import { DocMetadata, DocType, DuplicatedFile, + JsonDoc, JsonDocMetadata, RemoteOptions, SyncResultCombineDatabase, } from '../types'; import { GitDDBInterface } from '../types_gitddb'; import { Err } from '../error'; -import { DUPLICATED_FILE_POSTFIX, FILE_REMOVE_TIMEOUT, JSON_EXT } from '../const'; -import { getAllMetadata, toSortedJSONString } from '../utils'; +import { DUPLICATED_FILE_POSTFIX, FILE_REMOVE_TIMEOUT } from '../const'; +import { getAllMetadata } from '../utils'; +import { RemoteEngine, wrappingRemoteEngineError } from './remote_engine'; /** * Clone a remote repository and combine the current local working directory with it. + * TODO: Must catch errors * - * @remarks Must catch errors + * @throws {@link Err.FileRemoveTimeoutError} + * + * @throws # Errors from RemoteEngine[engineName].clone + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.NetworkError} + * @throws - {@link RemoteErr.HTTPError401AuthorizationRequired} + * @throws - {@link RemoteErr.HTTPError404NotFound} + * @throws - {@link RemoteErr.CannotConnectError} + * + * @throws - {@link RemoteErr.HttpProtocolRequiredError} + * @throws - {@link RemoteErr.InvalidRepositoryURLError} + * @throws - {@link RemoteErr.InvalidSSHKeyPathError} + * + * @throws - {@link RemoteErr.InvalidAuthenticationTypeError} + * + * @public */ // eslint-disable-next-line complexity export async function combineDatabaseWithTheirs ( gitDDB: GitDDBInterface, - remoteOptions: RemoteOptions + remoteOptions: RemoteOptions, + remoteName: string ): Promise { // Clone repository if remoteURL exists const remoteDir = gitDDB.workingDir + '_' + ulid(Date.now()); const tmpLocalDir = gitDDB.workingDir + '_' + ulid(Date.now()); - let remoteRepository: nodegit.Repository | undefined; + const duplicates: DuplicatedFile[] = []; try { - remoteRepository = await cloneRepository(remoteDir, remoteOptions, gitDDB.logger); - if (remoteRepository === undefined) { - // Remote repository not found. - // This will not occur after NoBaseMergeFoundError. - throw new Err.RemoteRepositoryNotFoundError(remoteOptions.remoteUrl!); - } - - const index = await remoteRepository.refreshIndex(); + await RemoteEngine[remoteOptions.connection!.engine!] + .clone(remoteDir, remoteOptions, remoteName, gitDDB.tsLogger) + .catch(err => { + throw wrappingRemoteEngineError(err); + }); + // Add refs to remote branch + const remoteCommitOid = await git.resolveRef({ + fs, + dir: remoteDir, + ref: `refs/remotes/origin/${gitDDB.defaultBranch}`, + }); + await git.writeRef({ + fs, + dir: remoteDir, + ref: `refs/remotes/${remoteName}/${gitDDB.defaultBranch}`, + value: remoteCommitOid, + force: true, + }); + // Overwrite upstream branch + await git.setConfig({ + fs, + dir: remoteDir, + path: `branch.${gitDDB.defaultBranch}.remote`, + value: remoteName, + }); + await git.setConfig({ + fs, + dir: remoteDir, + path: `branch.${gitDDB.defaultBranch}.merge`, + value: `refs/heads/${gitDDB.defaultBranch}`, + }); - const localMetadataList: DocMetadata[] = await getAllMetadata(gitDDB.repository()!); - const remoteMetadataList: DocMetadata[] = await getAllMetadata(remoteRepository); + const localMetadataList: DocMetadata[] = await getAllMetadata( + gitDDB.workingDir, + gitDDB.serializeFormat + ); + const remoteMetadataList: DocMetadata[] = await getAllMetadata( + remoteDir, + gitDDB.serializeFormat + ); const remoteNames = remoteMetadataList.map(meta => meta.name); for (let i = 0; i < localMetadataList.length; i++) { @@ -63,7 +110,9 @@ export async function combineDatabaseWithTheirs ( await fs.ensureDir(dir); - const docType: DocType = localFilePath.endsWith('.json') ? 'json' : 'text'; + const docType: DocType = gitDDB.serializeFormat.hasObjectExtension(localFilePath) + ? 'json' + : 'text'; // eslint-disable-next-line max-depth if (docType === 'text') { // TODO: select binary or text by .gitattribtues @@ -83,21 +132,34 @@ export async function combineDatabaseWithTheirs ( const remoteFile = remoteMetadataList.find(data => data.name === meta.name); if (docType === 'json') { - const doc = fs.readJSONSync(localFilePath); + let doc: JsonDoc; + // eslint-disable-next-line max-depth + if (gitDDB.serializeFormat.format === 'front-matter') { + const txt = fs.readFileSync(localFilePath, { + encoding: 'utf8', + }); + const [, extension] = localFilePath.match(/.+(\..+?)$/)!; + doc = textToJsonDoc(txt, gitDDB.serializeFormat, extension); + } + else { + doc = fs.readJSONSync(localFilePath); + } + const _id = (meta as JsonDocMetadata)._id; // eslint-disable-next-line max-depth if (doc._id !== undefined) { doc._id = _id + postfix; } - duplicatedFileName = _id + postfix + JSON_EXT; + duplicatedFileName = _id + postfix + gitDDB.serializeFormat.extension(doc); duplicatedFileId = _id + postfix; - duplicatedFileExt = JSON_EXT; + duplicatedFileExt = gitDDB.serializeFormat.extension(doc); fs.writeFileSync( path.resolve(remoteDir, duplicatedFileName), - toSortedJSONString(doc) + gitDDB.serializeFormat.serialize(doc).data ); - const duplicatedOid = (await git.hashBlob({ object: toSortedJSONString(doc) })) - .oid; + const duplicatedOid = ( + await git.hashBlob({ object: gitDDB.serializeFormat.serialize(doc).data }) + ).oid; original = { _id, name: meta.name, @@ -130,8 +192,7 @@ export async function combineDatabaseWithTheirs ( type: docType, }; } - await index.addByPath(duplicatedFileName); - await index.write(); + await git.add({ fs, dir: remoteDir, filepath: duplicatedFileName }); duplicates.push({ original, @@ -141,14 +202,11 @@ export async function combineDatabaseWithTheirs ( else { // Copy localFilePath to remoteFilePath if remoteFilePath not exists await fs.copyFile(localFilePath, remoteFilePath); - await index.addByPath(meta.name); - await index.write(); + await git.add({ fs, dir: remoteDir, filepath: meta.name }); } } if (localMetadataList.length > 0) { - await index.writeTree(); - const commitMessage = 'combine database head with theirs'; await git.commit({ @@ -160,12 +218,8 @@ export async function combineDatabaseWithTheirs ( }); } - gitDDB.repository()!.cleanup(); await fs.rename(gitDDB.workingDir, tmpLocalDir); - if (remoteRepository) remoteRepository.cleanup(); - remoteRepository = undefined; - await fs.rename(remoteDir, gitDDB.workingDir); const userName = await git @@ -219,11 +273,8 @@ export async function combineDatabaseWithTheirs ( resolve(); }); }); - if (remoteRepository) remoteRepository.cleanup(); - remoteRepository = undefined; } - const repos = await nodegit.Repository.open(gitDDB.workingDir); - gitDDB.setRepository(repos!); + await gitDDB.loadDbInfo(); const result: SyncResultCombineDatabase = { diff --git a/src/remote/json_diff.ts b/src/remote/json_diff.ts index 94a9495e..6b52d23c 100644 --- a/src/remote/json_diff.ts +++ b/src/remote/json_diff.ts @@ -1,20 +1,20 @@ import { create } from '@sosuisen/jsondiffpatch'; -import { JsonDiffOptions, JsonDoc } from '../types'; +import { JsonDiffPatchOptions, JsonDoc } from '../types'; const JSON_DIFF_MINIMUM_TEXT_LENGTH = Number.MAX_SAFE_INTEGER; export class JsonDiff { private _jsonDiffPatch; - constructor (options?: JsonDiffOptions) { + constructor (options?: JsonDiffPatchOptions) { options ??= { - idOfSubtree: undefined, + keyInArrayedObject: undefined, plainTextProperties: undefined, }; - options.idOfSubtree ??= []; + options.keyInArrayedObject ??= []; const objectHash = (obj: { [key: string]: any }, index: number) => { - for (let i = 0; i < options!.idOfSubtree!.length; i++) { - const id = obj[options!.idOfSubtree![i]]; + for (let i = 0; i < options!.keyInArrayedObject!.length; i++) { + const id = obj[options!.keyInArrayedObject![i]]; if (id !== undefined) { return id; } diff --git a/src/remote/json_patch_ot.ts b/src/remote/json_patch_ot.ts index f2c6f0a3..734f03f4 100644 --- a/src/remote/json_patch_ot.ts +++ b/src/remote/json_patch_ot.ts @@ -1,13 +1,27 @@ +/* eslint-disable unicorn/prefer-spread */ /* eslint-disable max-depth */ -import { editOp, insertOp, JSONOp, moveOp, replaceOp, type } from 'ot-json1'; +import { editOp, insertOp, JSONOp, moveOp, removeOp, replaceOp, type } from 'ot-json1'; import { uniCount } from 'unicount'; -import { ConflictResolutionStrategyLabels, IJsonPatch, JsonDoc } from '../types'; +import { + ConflictResolutionStrategyLabels, + IJsonPatch, + JsonDiffPatchOptions, + JsonDoc, +} from '../types'; import { DEFAULT_CONFLICT_RESOLUTION_STRATEGY } from '../const'; export class JsonPatchOT implements IJsonPatch { - constructor () {} + private _keyOfUniqueArray: string[]; - private _textCreateOp (path: string[], startNum: number, str: string): JSONOp { + constructor (options?: JsonDiffPatchOptions) { + options ??= { + keyOfUniqueArray: undefined, + }; + this._keyOfUniqueArray = + options.keyOfUniqueArray !== undefined ? options.keyOfUniqueArray : []; + } + + private _textCreateOp (path: (string | number)[], startNum: number, str: string): JSONOp { if (startNum > 0) { return editOp(path, 'text-unicode', [startNum, str]); } @@ -15,7 +29,7 @@ export class JsonPatchOT implements IJsonPatch { } private _textReplaceOp ( - path: string[], + path: (string | number)[], startNum: number, from: string, to: string @@ -26,7 +40,7 @@ export class JsonPatchOT implements IJsonPatch { return editOp(path, 'text-unicode', [{ d: uniCount(from) }, to]); } - private _textDeleteOp (path: string[], startNum: number, str: string) { + private _textDeleteOp (path: (string | number)[], startNum: number, str: string) { if (startNum > 0) { return editOp(path, 'text-unicode', [startNum, { d: uniCount(str) }]); } @@ -34,7 +48,7 @@ export class JsonPatchOT implements IJsonPatch { } // eslint-disable-next-line complexity - getTextOp (path: string[], text: string): JSONOp { + getTextOp (path: (string | number)[], text: string): JSONOp { // From text patch const operators: JSONOp[] = []; const lines = text.split('\n'); @@ -96,37 +110,162 @@ export class JsonPatchOT implements IJsonPatch { } fromDiff (diff: { [key: string]: any }): JSONOp { - const operations: JSONOp = []; - const procTree = (ancestors: string[], tree: JsonDoc) => { + if (diff === undefined) return null; // Do not be undefined. Use null. + const operations: JSONOp[] = []; + const procTree = (ancestors: (string | number)[], tree: JsonDoc) => { const keys = Object.keys(tree); - let sortedKeys: string[]; - if (keys.includes('_t')) { + let sortedKeys: (string | number)[] = []; + const isArray = keys.includes('_t'); + + const nest: string[] = []; + const insOp: string[] = []; + const replOp: string[] = []; + const remOp: string[] = []; + const movOp: string[] = []; + const txtOp: string[] = []; + + if (isArray) { + // is Array + // underscore _ means 'remove' or 'move' operation keys.sort(); // 1, 2, 3, _1, _2, _3 + // console.log('## start parse keys: ' + JSON.stringify(keys)); let underBarStart = 0; for (underBarStart = 0; underBarStart < keys.length; underBarStart++) { if (keys[underBarStart].startsWith('_')) { break; } } - const noBar = keys.slice(0, underBarStart); - const underBar = keys.slice(underBarStart, keys.length); - sortedKeys = underBar.concat(noBar); // _1, _2, _3, 1, 2, 3 + + // no bar: insert/replace/text + keys.slice(0, underBarStart).forEach(key => { + if (!Array.isArray(tree[key])) nest.push(key); + else if (tree[key].length === 1) insOp.push(key); + else if (tree[key].length === 2) replOp.push(key); + else if (tree[key].length === 3 && typeof tree[key][0] === 'string') + txtOp.push(key); + }); + + // underBar: remove/move + // eslint-disable-next-line complexity + keys.slice(underBarStart, keys.length).forEach(key => { + if (!Array.isArray(tree[key])) nest.push(key); + else if (tree[key].length === 3) { + const arr = tree[key]; + if (arr[1] === 0 && arr[2] === 0) remOp.push(key); + else if (arr[0] === '' && arr[2] === 3) movOp.push(key); + } + }); + movOp.sort( + (a, b) => + // sort by destination position + tree[a][1] - tree[b][1] + ); + insOp.sort( + (a, b) => + // sort by destination position + parseInt(a, 10) - parseInt(b, 10) + ); + // sort order: replace, text, remove, insert, move + sortedKeys = sortedKeys.concat(replOp, txtOp, remOp, movOp, insOp, nest); } else { + // is Object sortedKeys = keys.sort(); } + const removedIndex: (string | number)[] = []; + const insertedIndex: (string | number)[] = []; + const movedOperation: { from: number; to: number }[] = []; + // eslint-disable-next-line complexity sortedKeys.forEach(key => { + // console.log('# ' + key); if (Array.isArray(tree[key])) { const arr = tree[key] as any[]; if (arr.length === 1) { - operations.push(insertOp(ancestors.concat(key), arr[0])!); + // Insert + if (isArray && typeof key === 'string') { + key = parseInt(key.replace(/^_/, ''), 10); // Remove heading underscore + } + if (isArray) { + let dstOffset = 0; + movOp.forEach(mop => { + const from = parseInt(mop, 10); + const to = tree[mop][1] as number; + if (from < (key as number) && to > key) dstOffset++; + if (from > (key as number) && to < key) dstOffset--; + }); + operations.push( + insertOp(ancestors.concat((key as number) + dstOffset), arr[0])! + ); + insertedIndex.push(key); + } + else { + operations.push(insertOp(ancestors.concat(key), arr[0])!); + } } else if (arr.length === 2) { + // Replace + if (isArray && typeof key === 'string') { + key = parseInt(key.replace(/^_/, ''), 10); // Remove heading underscore + } operations.push(replaceOp(ancestors.concat(key), arr[0], arr[1])!); } else if (arr.length === 3) { const firstItem = arr[0]; - if (typeof firstItem === 'string') { + if (isArray && typeof key === 'string') { + key = parseInt(key.replace(/^_/, ''), 10); // Remove heading underscore + } + if (arr[1] === 0 && arr[2] === 0) { + // Remove + // See https://github.com/benjamine/jsondiffpatch/blob/master/docs/deltas.md + if (typeof key === 'string') { + // Remove property + operations.push(removeOp(ancestors.concat(key))); + } + else { + // Remove from array + const offset = -removedIndex.length; + operations.push(removeOp(ancestors.concat((key as number) + offset))); + removedIndex.push(key); + } + } + else if (arr[0] === '' && arr[2] === 3) { + // Moved + // See https://github.com/benjamine/jsondiffpatch/blob/master/docs/deltas.md + if (isArray) { + let offset = 0; + removedIndex.forEach(index => { + if (parseInt(index as string, 10) <= parseInt(key as string, 10)) + offset--; + }); + /* + insertedIndex.forEach(index => { + if (parseInt(index as string, 10) <= parseInt(key as string, 10)) + offset++; + }); + */ + movedOperation.forEach(mop => { + if (mop.from < (key as number) && mop.to > arr[1]) offset--; + if (mop.from > (key as number) && mop.to < arr[1]) offset++; + }); + + let dstOffset = 0; + insOp.forEach(iop => { + if (parseInt(iop as string, 10) <= parseInt(arr[1] as string, 10)) + dstOffset--; + }); + operations.push( + moveOp( + ancestors.concat((key as number) + offset), + ancestors.concat((arr[1] as number) + dstOffset) + ) + ); + movedOperation.push({ from: key as number, to: arr[1] }); + } + else { + operations.push(moveOp(ancestors.concat(key), ancestors.concat(arr[1]))); + } + } + else if (typeof firstItem === 'string') { let isTextPatch = firstItem.match(/^@@ -\d+?,\d+? \+\d+?,\d+? @@\n/m); if (!isTextPatch) isTextPatch = firstItem.match(/^@@ -\d+? \+\d+?,\d+? @@\n/m); @@ -141,19 +280,34 @@ export class JsonPatchOT implements IJsonPatch { } } } + else if (typeof tree[key] === 'object') { + if (isArray && typeof key === 'string') { + key = parseInt(key.replace(/^_/, ''), 10); // Remove heading underscore + } + procTree(ancestors.concat(key), tree[key]); + } }); }; procTree([], diff); if (operations.length === 1) { return (operations[0] as unknown) as JSONOp; } - return operations; + /** + * A path can be a flat array format in the specification. e.g.) ['x', 'y', {i:2}] + * https://github.com/ottypes/json1/blob/master/spec.md + * However type.transform function does not accept the flat array format. + * Use a nested array format instead. e.g.) ['x', ['y', {i:2}]]. + * type.compose converts the flat array format to the nested array format. + */ + const reducedOperations = operations.reduce(type.compose, null); + return reducedOperations; } apply (doc: JsonDoc, op: JSONOp): JsonDoc { return (type.apply(doc, op) as unknown) as JsonDoc; } + // eslint-disable-next-line complexity patch ( docOurs: JsonDoc, diffOurs: { [key: string]: any }, @@ -165,12 +319,14 @@ export class JsonPatchOT implements IJsonPatch { if (docTheirs === undefined || diffTheirs === undefined) { return (type.apply(docOurs, this.fromDiff(diffOurs)) as unknown) as JsonDoc; } - // console.log(diffOurs); - // console.log(diffTheirs); + // console.log(JSON.stringify(diffOurs)); + // console.log(JSON.stringify(diffTheirs)); const opOurs = this.fromDiff(diffOurs); + // console.log('opOurs: ' + JSON.stringify(opOurs) + '\n'); const opTheirs = this.fromDiff(diffTheirs); + // console.log('opTheirs: ' + JSON.stringify(opTheirs) + '\n'); const transformedOp = this.transform(opTheirs, opOurs, strategy!); - // console.log('# transformed: ' + JSON.stringify(transformedOp)); + // console.log('# transformed: ' + JSON.stringify(transformedOp) + '\n'); let newDoc: JsonDoc; if (strategy.startsWith('ours')) { newDoc = (type.apply(docOurs, transformedOp!) as unknown) as JsonDoc; @@ -179,6 +335,75 @@ export class JsonPatchOT implements IJsonPatch { // console.log('# apply to: ' + JSON.stringify(docTheirs)); newDoc = (type.apply(docTheirs, transformedOp!) as unknown) as JsonDoc; } + + if (this._keyOfUniqueArray !== undefined && this._keyOfUniqueArray.length > 0) { + const ourTrees: JsonDoc[] = [docOurs]; + const theirTrees: JsonDoc[] = [docTheirs]; + const trees: JsonDoc[] = [newDoc]; + while (trees.length > 0) { + const currentTree = trees.pop(); + const currentOurTree = ourTrees.pop(); + const currentTheirTree = theirTrees.pop(); + if ( + currentTree === undefined || + currentOurTree === undefined || + currentTheirTree === undefined + ) + break; + + Object.keys(currentTree!).forEach(key => { + if (!Array.isArray(currentTree![key]) && typeof currentTree![key] === 'object') { + trees.push(currentTree![key]); + ourTrees.push(currentOurTree![key]); + theirTrees.push(currentTheirTree![key]); + } + else if (this._keyOfUniqueArray.includes(key)) { + const array = currentTree![key] as any[]; + const ourArray = currentOurTree![key] as any[]; + const theirArray = currentTheirTree![key] as any[]; + if (Array.isArray(array)) { + // eslint-disable-next-line complexity + const unique = array.filter((x, i, self) => { + if (self.indexOf(x) === i && i !== self.lastIndexOf(x)) { + if ( + strategy!.startsWith('ours') && + ourArray.indexOf(x) <= theirArray.indexOf(x) + ) { + return true; + } + else if ( + strategy!.startsWith('theirs') && + ourArray.indexOf(x) > theirArray.indexOf(x) + ) { + return true; + } + return false; + } + else if (self.indexOf(x) !== i && i === self.lastIndexOf(x)) { + if ( + strategy!.startsWith('ours') && + ourArray.indexOf(x) > theirArray.indexOf(x) + ) { + return true; + } + else if ( + strategy!.startsWith('theirs') && + ourArray.indexOf(x) <= theirArray.indexOf(x) + ) { + return true; + } + return false; + } + + return true; + }); + currentTree![key] = unique; + } + } + }); + } + } + return newDoc; } @@ -190,18 +415,23 @@ export class JsonPatchOT implements IJsonPatch { ): [JSONOp, JSONOp, JSONOp | undefined] { let transformedOp; try { - // console.log('trying ours: ' + JSON.stringify(_opOurs)); - // console.log('trying theirs: ' + JSON.stringify(_opTheirs)); + // console.log('trying ours: ' + JSON.stringify(opOurs)); + // console.log('trying theirs: ' + JSON.stringify(opTheirs)); if (strategy.startsWith('ours')) { transformedOp = type.transform(opTheirs, opOurs, 'right'); } else { transformedOp = type.transform(opOurs, opTheirs, 'right'); } - } catch (err) { - if (err.conflict) { - // console.log('conflict: ' + JSON.stringify(err.conflict)); - const conflict = err.conflict as { type: number; op1: any[]; op2: any[] }; + } catch (err: unknown) { + // console.log('conflict: ' + JSON.stringify(err)); + if ((err as { conflict: any }).conflict) { + // console.log('conflict: ' + JSON.stringify((err as { conflict: any }).conflict)); + const conflict = (err as { conflict: any }).conflict as { + type: number; + op1: any[]; + op2: any[]; + }; let conflictedOperation; // Remove conflicted op from targetOperations @@ -215,59 +445,66 @@ export class JsonPatchOT implements IJsonPatch { conflictedOperation = conflict.op2; targetOperations = JSON.parse(JSON.stringify(opOurs)); } - // Location is array. - const conflictedLocation = conflictedOperation.slice(0, -1); + // Get JSON array of conflicted path + const conflictedPath = JSON.stringify(conflictedOperation.slice(0, -1)); + // Get p, r, d, i, e const conflictedCommands = Object.keys( conflictedOperation[conflictedOperation.length - 1] ); - if (targetOperations.length > 1 && !Array.isArray(targetOperations[0])) { - // Operation (e.g. {p: 0}) - const op: { [command: string]: string } = - targetOperations[targetOperations.length - 1]; - conflictedCommands.forEach(command => delete op[command]); - targetOperations[targetOperations.length - 1] = op; - } - else if (targetOperations.length > 1) { - // Search conflictedLocation in targetOperations - let loc = -1; - for (let i = 0; i < targetOperations.length; i++) { - if (targetOperations[i].length - 1 === conflictedLocation.length) { - for (let j = 0; j < conflictedLocation.length; j++) { - if (targetOperations[i][j] !== conflictedLocation[j]) { - break; - } - if (j === conflictedLocation.length - 1) { - loc = i; - } - } - if (loc >= 0) { - break; - } + const resolvedOperations: any[] = []; + + const stack: { pathFromRoot: string[]; opArray: any[] }[] = [ + { + pathFromRoot: [], + opArray: targetOperations, + }, + ]; + while (stack.length > 0) { + const { pathFromRoot, opArray } = stack.pop()!; + + if (opArray.length === 0) continue; + + const opPath: string[] = []; + for (const opElm of opArray) { + if (typeof opElm === 'string') { + pathFromRoot.push(opElm); } - } - if (loc >= 0) { - const op: { [command: string]: string } = - targetOperations[loc][targetOperations[loc].length - 1]; - // delete command - conflictedCommands.forEach(command => delete op[command]); - if (Object.keys(op).length > 0) { - targetOperations[loc][targetOperations[loc].length - 1] = op; + else if (Array.isArray(opElm)) { + stack.push({ + pathFromRoot: [...pathFromRoot], + opArray: JSON.parse(JSON.stringify(opElm)), + }); } else { - targetOperations.splice(loc, 1); - } - if (targetOperations.length === 1) { - targetOperations = targetOperations[0]; + // Operation (e.g. {p: 0}) + if (JSON.stringify(pathFromRoot) === conflictedPath) { + conflictedCommands.forEach(command => delete opElm[command]); + } + if (Object.keys(opElm).length > 0) { + const resolvedOp = pathFromRoot.concat(opElm); + resolvedOperations.push(resolvedOp); + } } - // console.log('# resolved: ' + JSON.stringify(targetOperations)); } } + // console.log('# resolved: ' + JSON.stringify(resolvedOperations)); + const resolvedOperationsComposed = resolvedOperations.reduce(type.compose, null); + // console.log('# resolved composed: ' + JSON.stringify(resolvedOperationsComposed)); + if (strategy.startsWith('ours')) { - return [JSON.parse(JSON.stringify(opOurs)), targetOperations, undefined]; + return [ + JSON.parse(JSON.stringify(opOurs)), + resolvedOperationsComposed, + undefined, + ]; } - return [targetOperations, JSON.parse(JSON.stringify(opTheirs)), undefined]; + return [ + resolvedOperationsComposed, + JSON.parse(JSON.stringify(opTheirs)), + undefined, + ]; } throw err; } diff --git a/src/remote/net.ts b/src/remote/net.ts deleted file mode 100644 index bb8047b4..00000000 --- a/src/remote/net.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -import { Socket } from 'net'; -import http from 'http'; -import https from 'https'; -import { Err } from '../error'; - -/** - * Ping to host - */ -/* -export const ping = ( - port: number, - address: string, - timeout: number -): Promise<{ ok: boolean; error?: Error }> => { - return new Promise(resolve => { - // Create a new tcp socket - const socket = new Socket(); - // Connect to the given host - socket.connect(port, address, () => { - socket.destroy(); - // Resolve with the latency of this attempt - resolve({ ok: true }); - }); - // Make sure we catch any errors thrown by the socket - socket.on('error', error => { - socket.destroy(); - resolve({ ok: false, error }); - }); - - socket.setTimeout(timeout, () => { - socket.destroy(); - resolve({ ok: false, error: new Error('Request timeout') }); - }); - }); -}; -*/ - -/** - * Check HTTP connection - * @remarks - * requestTimeout and socketTimeout must be greater than 0. - * Timeout is not set if timeout is less than 0. - * - * @throws {@link Err.HttpProtocolRequiredError} - * @throws {@link Err.HTTPNetworkError} - * @throws {@link Err.RequestTimeoutError} - * @throws {@link Err.SocketTimeoutError} - * - * @internal - */ -export function checkHTTP ( - url: string, - requestTimeout: number, - socketTimeout?: number -): Promise<{ ok: boolean; code?: number }> { - // timeout must be greater than 0 - socketTimeout ??= requestTimeout; - if (requestTimeout === 0) { - requestTimeout = 1; - } - if (socketTimeout === 0) { - socketTimeout = 1; - } - return new Promise((resolve, reject) => { - // Send GET - let request: ( - // eslint-disable-next-line node/no-unsupported-features/node-builtins - options: string | https.RequestOptions | URL, - callback?: ((res: http.IncomingMessage) => void) | undefined - ) => http.ClientRequest; - if (url.startsWith('http:')) { - request = http.request; - } - else if (url.startsWith('https:')) { - request = https.request; - } - else { - reject(new Err.HttpProtocolRequiredError(url)); - } - - let socket: Socket; - const req = request!(url, res => { - req.removeAllListeners(); - if (socket) { - socket.removeAllListeners(); - } - req.destroy(); - resolve({ ok: true, code: res.statusCode }); - }); - req.on('error', error => { - // network error - req.removeAllListeners(); - if (socket) { - socket.removeAllListeners(); - } - req.destroy(); - reject(new Err.HTTPNetworkError(error.message)); - }); - - if (requestTimeout > 0) { - req.setTimeout(requestTimeout, () => { - req.removeAllListeners(); - if (socket) { - socket.removeAllListeners(); - } - req.destroy(); - console.log(' - request timeout error: ' + requestTimeout); - reject(new Err.RequestTimeoutError(url)); - }); - } - - if (socketTimeout! > 0) { - req.on('socket', function (mySocket: Socket) { - socket = mySocket; - socket.setTimeout(socketTimeout!); - socket.on('timeout', () => { - req.removeAllListeners(); - if (socket) { - socket.removeAllListeners(); - } - req.destroy(); - console.log(' - socket timeout error: ' + socketTimeout); - reject(new Err.SocketTimeoutError(url)); - }); - }); - } - - req.end(); - }); -} diff --git a/src/remote/push_worker.ts b/src/remote/push_worker.ts index 28a233f8..8ab95a7d 100644 --- a/src/remote/push_worker.ts +++ b/src/remote/push_worker.ts @@ -6,102 +6,52 @@ * found in the LICENSE file in the root directory of gitDDB source tree. */ -import nodegit from '@sosuisen/nodegit'; import git from 'isomorphic-git'; import fs from 'fs-extra'; -import { CONSOLE_STYLE } from '../utils'; -import { Err } from '../error'; import { GitDDBInterface } from '../types_gitddb'; -import { NormalizedCommit, SyncResultPush, TaskMetadata } from '../types'; +import { + ChangedFile, + NormalizedCommit, + SyncResultNop, + SyncResultPush, + TaskMetadata, +} from '../types'; import { SyncInterface } from '../types_sync'; -import { calcDistance, getChanges, getCommitLogs } from './worker_utils'; +import { getChanges, getCommitLogs } from './worker_utils'; +import { RemoteEngine, RemoteErr, wrappingRemoteEngineError } from './remote_engine'; /** - * git push + * Push and get changes * - * @throws {@link Err.UnfetchedCommitExistsError} (from this and validatePushResult()) - * @throws {@link Err.SyncWorkerFetchError} (from validatePushResult()) - * @throws {@link Err.GitPushError} (from NodeGit.Remote.push()) - */ -async function push (gitDDB: GitDDBInterface, sync: SyncInterface): Promise { - const repos = gitDDB.repository()!; - const remote: nodegit.Remote = await repos.getRemote('origin'); - await remote - .push(['refs/heads/main:refs/heads/main'], { - callbacks: sync.credentialCallbacks, - }) - .catch((err: Error) => { - if ( - err.message.startsWith( - 'cannot push because a reference that you are trying to update on the remote contains commits that are not present locally' - ) - ) { - throw new Err.UnfetchedCommitExistsError(); - } - throw new Err.GitPushError(err.message); - }); - // gitDDB.logger.debug(CONSOLE_STYLE.BgWhite().FgBlack().tag()`sync_worker: May pushed.`); - await validatePushResult(gitDDB, sync); -} - -/** - * NodeGit.Remote.push does not return valid error in race condition, - * so check is needed. + * @throws # Errors from push + * @throws - {@link InvalidGitRemoteError} + * @throws - {@link UnfetchedCommitExistsError} + * @throws - {@link InvalidURLFormatError} + * @throws - {@link NetworkError} + * @throws - {@link HTTPError401AuthorizationRequired} + * @throws - {@link HTTPError404NotFound} + * @throws - {@link HTTPError403Forbidden} + * @throws - {@link CannotConnectError} + * @throws - {@link CannotConnectError} + * @throws - {@link HttpProtocolRequiredError} + * @throws - {@link InvalidRepositoryURLError} + * @throws - {@link InvalidSSHKeyPathError} + * @throws - {@link InvalidAuthenticationTypeError} * - * @throws {@link Err.SyncWorkerFetchError} - * @throws {@link Err.UnfetchedCommitExistsError} - */ -async function validatePushResult ( - gitDDB: GitDDBInterface, - sync: SyncInterface -): Promise { - const repos = gitDDB.repository()!; - await repos - .fetch('origin', { - callbacks: sync.credentialCallbacks, - }) - .catch(err => { - throw new Err.SyncWorkerFetchError(err.message); - }); - - const localCommitOid = await git.resolveRef({ - fs, - dir: gitDDB.workingDir, - ref: 'HEAD', - }); - const remoteCommitOid = await git.resolveRef({ - fs, - dir: gitDDB.workingDir, - ref: 'refs/remotes/origin/main', - }); - const distance = await calcDistance(gitDDB.workingDir, localCommitOid, remoteCommitOid); - - if (distance.behind > 0) { - gitDDB.logger.debug( - CONSOLE_STYLE.bgWhite() - .fgBlack() - .tag()`sync_worker: push failed: ahead ${distance.ahead} behind ${distance.behind}` - ); - - throw new Err.UnfetchedCommitExistsError(); - } -} - -/** - * Push and get changes + * @throws # Errors from getChanges + * @throws - {@link Err.InvalidJsonObjectError} * - * @throws {@link Err.RepositoryNotOpenError} - * @throws {@link Err.UnfetchedCommitExistsError} (from push() and validatePushResult()) - * @throws {@link Err.SyncWorkerFetchError} (from validatePushResult()) - * @throws {@link Err.InvalidJsonObjectError} (from getChanges()) - * @throws Error (Other errors from NodeGit.Remote.push()) + * @internal */ +// eslint-disable-next-line complexity export async function pushWorker ( gitDDB: GitDDBInterface, sync: SyncInterface, taskMetadata: TaskMetadata, - skipStartEvent = false -): Promise { + skipStartEvent = false, + afterMerge = false +): Promise { + const syncOptions = sync.options; if (!skipStartEvent) { sync.eventHandlers.start.forEach(listener => { listener.func( @@ -139,8 +89,12 @@ export async function pushWorker ( let localCommitOid: string; - let remoteCommitOid = await git - .resolveRef({ fs, dir: gitDDB.workingDir, ref: 'refs/remotes/origin/main' }) + const remoteCommitOid = await git + .resolveRef({ + fs, + dir: gitDDB.workingDir, + ref: `refs/remotes/${sync.remoteName}/${gitDDB.defaultBranch}`, + }) .catch(() => undefined); if (headCommit.commit.parent.length === 2) { @@ -151,14 +105,16 @@ export async function pushWorker ( localCommitOid = headCommitOid; } - let baseCommitOid: string; + let baseCommitOid: string | undefined; if (remoteCommitOid === undefined) { // This is the first push in this repository. // Get the first commit. const logs = await git.log({ fs, dir: gitDDB.workingDir }); baseCommitOid = logs[logs.length - 1].oid; - remoteCommitOid = baseCommitOid; + if (baseCommitOid === localCommitOid) { + baseCommitOid = undefined; + } } else { [baseCommitOid] = await git.findMergeBase({ @@ -169,8 +125,44 @@ export async function pushWorker ( } // Push - await push(gitDDB, sync); - const remoteChanges = await getChanges(gitDDB.workingDir, remoteCommitOid, headCommitOid); + const res = await RemoteEngine[sync.engine] + .push( + gitDDB.workingDir, + syncOptions, + sync.remoteName, + gitDDB.defaultBranch, + gitDDB.defaultBranch, + gitDDB.tsLogger + ) + .catch(err => err); + + if (res instanceof Error) { + const error = wrappingRemoteEngineError(res); + if (error instanceof RemoteErr.UnfetchedCommitExistsError) { + if (localCommitOid === remoteCommitOid) { + return { action: 'nop' }; + } + } + throw error; + } + // NodeGit does not throw UnfetchedCommitExistsError when localCommitOid equals remoteCommitOid, + // So check it again here. + if (localCommitOid === remoteCommitOid) { + return { action: 'nop' }; + } + + let remoteChanges: ChangedFile[] | undefined; + if (afterMerge) { + remoteChanges = undefined; + } + else { + remoteChanges = await getChanges( + gitDDB.workingDir, + remoteCommitOid, + headCommitOid, + gitDDB.serializeFormat + ); + } const syncResult: SyncResultPush = { action: 'push', @@ -181,7 +173,7 @@ export async function pushWorker ( // Get a list of commits which will be pushed to remote. let commitListRemote: NormalizedCommit[] | undefined; - if (sync.options.includeCommits) { + if (syncOptions.includeCommits) { commitListRemote = await getCommitLogs( gitDDB.workingDir, headCommitOid, diff --git a/src/remote/remote_engine.ts b/src/remote/remote_engine.ts new file mode 100644 index 00000000..5b946750 --- /dev/null +++ b/src/remote/remote_engine.ts @@ -0,0 +1,172 @@ +/* eslint-disable unicorn/custom-error-definition */ +/* eslint-disable @typescript-eslint/naming-convention */ +import { Logger } from 'tslog'; +import { RemoteOptions } from '../types'; + +/** + * RemoteEngine + * + * @public + */ +export const RemoteEngine: { [key: string]: RemoteEngineInterface } = {}; + +/** + * RemoteEngineInterface + * + * @internal + */ +export interface RemoteEngineInterface { + type: string; + name: string; + + checkFetch: ( + workingDir: string, + options: RemoteOptions, + remoteName?: string, + logger?: Logger + ) => Promise; + fetch: ( + workingDir: string, + remoteOptions: RemoteOptions, + remoteName?: string, + localBranchName?: string, + remoteBranchName?: string, + logger?: Logger + ) => Promise; + push: ( + workingDir: string, + remoteOptions: RemoteOptions, + remoteName?: string, + localBranch?: string, + remoteBranch?: string, + logger?: Logger + ) => Promise; + clone: ( + workingDir: string, + remoteOptions: RemoteOptions, + remoteName: string, + logger?: Logger + ) => Promise; +} + +class BaseError extends Error { + constructor (e: string) { + super(e); + this.name = new.target.name; + Object.setPrototypeOf(this, new.target.prototype); + } +} + +/** + * RemoteError + * + * @public + */ +export namespace RemoteErr { + /** + * @privateRemarks + * Copy error message from parent + */ + export class CannotConnectError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class HTTPError401AuthorizationRequired extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class HTTPError403Forbidden extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class HTTPError404NotFound extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class InvalidAuthenticationTypeError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class InvalidGitRemoteError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class InvalidRepositoryURLError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class InvalidSSHKeyPathError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class InvalidURLFormatError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class NetworkError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } + export class UnfetchedCommitExistsError extends BaseError { + constructor (mes: unknown) { + super(''); + this.message = mes as string; + } + } +} + +/** + * wrappingRemoteEngineError + * + * @internal + */ +// eslint-disable-next-line complexity +export function wrappingRemoteEngineError (remoteEngineError: BaseError) { + // Do not use 'instanceof' to compare git-documentdb-remote-errors + switch (remoteEngineError.name) { + case 'CannotConnectError': + return new RemoteErr.CannotConnectError(remoteEngineError.message); + case 'HTTPError401AuthorizationRequired': + return new RemoteErr.HTTPError401AuthorizationRequired(remoteEngineError.message); + case 'HTTPError403Forbidden': + return new RemoteErr.HTTPError403Forbidden(remoteEngineError.message); + case 'HTTPError404NotFound': + return new RemoteErr.HTTPError404NotFound(remoteEngineError.message); + case 'InvalidAuthenticationTypeError': + return new RemoteErr.InvalidAuthenticationTypeError(remoteEngineError.message); + case 'InvalidGitRemoteError': + return new RemoteErr.InvalidGitRemoteError(remoteEngineError.message); + case 'InvalidRepositoryURLError': + return new RemoteErr.InvalidRepositoryURLError(remoteEngineError.message); + case 'InvalidSSHKeyPathError': + return new RemoteErr.InvalidSSHKeyPathError(remoteEngineError.message); + case 'InvalidURLFormatError': + return new RemoteErr.InvalidURLFormatError(remoteEngineError.message); + case 'NetworkError': + return new RemoteErr.NetworkError(remoteEngineError.message); + case 'UnfetchedCommitExistsError': + return new RemoteErr.UnfetchedCommitExistsError(remoteEngineError.message); + default: + return new Error(remoteEngineError.message); + } +} diff --git a/src/remote/remote_repository.ts b/src/remote/remote_repository.ts index 8ac2826a..9c9f804b 100644 --- a/src/remote/remote_repository.ts +++ b/src/remote/remote_repository.ts @@ -6,18 +6,12 @@ * found in the LICENSE file in the root directory of this source tree. */ -import nodegit from '@sosuisen/nodegit'; import { Octokit } from '@octokit/rest'; import { Err } from '../error'; import { RemoteOptions } from '../types'; import { NETWORK_RETRY, NETWORK_RETRY_INTERVAL } from '../const'; import { sleep } from '../utils'; -/** - * GitOrigin - */ -type GitRemoteAction = 'add' | 'change' | 'exist'; - /** * Remote repository class * @@ -25,14 +19,11 @@ type GitRemoteAction = 'add' | 'change' | 'exist'; */ export class RemoteRepository { private _options: RemoteOptions; - private _octokit: Octokit | undefined; /** * Constructor * - * @throws {@link Err.InvalidAuthenticationTypeError} - * * @public */ constructor (options: RemoteOptions) { @@ -53,19 +44,17 @@ export class RemoteRepository { else if (this._options.connection.type === 'none') { // nop } - else { - throw new Err.InvalidAuthenticationTypeError(this._options.connection.type); - } } /** * Create a repository on a remote site + * * @remarks * connection.type must be 'github' * * @throws {@link Err.UndefinedPersonalAccessTokenError} * @throws {@link Err.PersonalAccessTokenForAnotherAccountError} - * @throws {@link Err.CannotConnectError} + * @throws {@link Err.CannotConnectRemoteRepositoryError} * * may include the following errors: * @@ -121,7 +110,11 @@ export class RemoteRepository { await sleep(NETWORK_RETRY_INTERVAL); } if (result instanceof Error) { - throw new Err.CannotConnectError(retry, this._options.remoteUrl!, result.message); + throw new Err.CannotConnectRemoteRepositoryError( + retry, + this._options.remoteUrl!, + result.message + ); } } else { @@ -133,11 +126,12 @@ export class RemoteRepository { /** * Delete a repository on a remote site + * * @remarks * connection.type must be 'github' * * @throws {@link Err.UndefinedPersonalAccessTokenError} - * @throws {@link Err.CannotConnectError} + * @throws {@link Err.CannotConnectRemoteRepositoryError} * * may include the following errors: * @@ -186,7 +180,11 @@ export class RemoteRepository { await sleep(NETWORK_RETRY_INTERVAL); } if (result instanceof Error) { - throw new Err.CannotConnectError(retry, this._options.remoteUrl!, result.message); + throw new Err.CannotConnectRemoteRepositoryError( + retry, + this._options.remoteUrl!, + result.message + ); } } else { @@ -195,188 +193,4 @@ export class RemoteRepository { ); } } - - /** - * Get or create Git remote named 'origin' - * - * (git remote add) - * - * @internal - */ - // eslint-disable-next-line complexity - private async _getOrCreateGitRemote ( - repos: nodegit.Repository, - remoteURL: string - ): Promise<[GitRemoteAction, nodegit.Remote]> { - let result: GitRemoteAction; - // Check if remote repository already exists - let remote = await nodegit.Remote.lookup(repos, 'origin').catch(() => {}); - if (remote === undefined) { - // Add remote repository - remote = await nodegit.Remote.create(repos, 'origin', remoteURL); - result = 'add'; - } - else if (remote.url() !== remoteURL) { - nodegit.Remote.setUrl(repos, 'origin', remoteURL); - result = 'change'; - } - else { - result = 'exist'; - } - return [result, remote]; - } - - /** - * Check connection by FETCH - * - * @throws {@link Err.InvalidURLError} - * @throws {@link Err.RemoteRepositoryNotFoundError} - * @throws Error (Other errors from NodeGit.Remote#connect()) - * - * @internal - */ - // eslint-disable-next-line complexity - private async _checkFetch ( - remote: nodegit.Remote, - credentialCallbacks: { [key: string]: any } - ): Promise<'exist'> { - const remoteURL = remote.url(); - const error = String( - await remote - .connect(nodegit.Enums.DIRECTION.FETCH, credentialCallbacks) - .catch(err => err) - ); - await remote.disconnect(); - // if (error !== 'undefined') console.warn('connect fetch error: ' + error); - switch (true) { - case error === 'undefined': - break; - case error.startsWith('Error: unsupported URL protocol'): - case error.startsWith('Error: failed to resolve address'): - case error.startsWith('Error: failed to send request'): - throw new Err.InvalidURLError(remoteURL + ':' + error); - case error.startsWith('Error: unexpected HTTP status code: 4'): // 401, 404 on Ubuntu - case error.startsWith('Error: request failed with status code: 4'): // 401, 404 on Windows - case error.startsWith('Error: Method connect has thrown an error'): - case error.startsWith('Error: ERROR: Repository not found'): - // Remote repository does not exist, or you do not have permission to the private repository - throw new Err.RemoteRepositoryNotFoundError(remoteURL + ':' + error); - case error.startsWith( - 'Error: remote credential provider returned an invalid cred type' - ): // on Ubuntu - case error.startsWith('Failed to retrieve list of SSH authentication methods'): - case error.startsWith('Error: too many redirects or authentication replays'): - throw new Err.FetchPermissionDeniedError(error); - default: - throw new Error(error); - } - return 'exist'; - } - - /** - * Check connection by PUSH - * - * @throws {@link Err.InvalidURLError} - * @throws {@link Err.RemoteRepositoryNotFoundError} - * @throws {@link Err.PushPermissionDeniedError} - * @throws Error (Other errors from NodeGit.Remote#connect()) - * - * @internal - */ - // eslint-disable-next-line complexity - private async _checkPush ( - remote: nodegit.Remote, - credentialCallbacks: { [key: string]: any } - ) { - const remoteURL = remote.url(); - const error = String( - await remote - .connect(nodegit.Enums.DIRECTION.PUSH, credentialCallbacks) - .catch(err => err) - ); - await remote.disconnect(); - // if (error !== 'undefined') console.warn('connect push error: ' + error); - switch (true) { - case error === 'undefined': - break; - case error.startsWith('Error: unsupported URL protocol'): - case error.startsWith('Error: failed to resolve address'): - case error.startsWith('Error: failed to send request'): - throw new Err.InvalidURLError(remoteURL); - case error.startsWith('Error: unexpected HTTP status code: 4'): // 401, 404 on Ubuntu - case error.startsWith('Error: request failed with status code: 4'): // 401, 404 on Windows - case error.startsWith('Error: Method connect has thrown an error'): - case error.startsWith('Error: ERROR: Repository not found'): { - // Remote repository does not exist, or you do not have permission to the private repository - throw new Err.RemoteRepositoryNotFoundError(remoteURL); - } - // Invalid personal access token - // Personal access token is read only - case error.startsWith( - 'Error: remote credential provider returned an invalid cred type' - ): // on Ubuntu - case error.startsWith('Error: too many redirects or authentication replays'): - case error.startsWith('Error: ERROR: Permission to'): { - throw new Err.PushPermissionDeniedError(error); - } - default: - throw new Error(error); - } - return 'ok'; - } - - /** - * Set a remote repository and connect to the remote repository. - * A remote repository will be created if not exists. - * - * @throws {@link Err.UndefinedPersonalAccessTokenError} (from RemoteRepository#create()) - * @throws {@link Err.PersonalAccessTokenForAnotherAccountError} (from RemoteRepository#create()) - * @throws {@link Err.CannotConnectError} (from RemoteRepository#create()) - * @throws {@link Err.AuthenticationTypeNotAllowCreateRepositoryError} (from RemoteRepository#create()) - * @throws {@link Err.FetchConnectionFailedError} - * @throws {@link Err.CannotCreateRemoteRepositoryError} - * @throws {@link Err.PushConnectionFailedError} - * - * @public - */ - async connect ( - repos: nodegit.Repository, - credentialCallbacks: { [key: string]: any }, - onlyFetch?: boolean - ): Promise<[GitRemoteAction, 'exist' | 'create']> { - // Get NodeGit.Remote - const [gitResult, remote] = await this._getOrCreateGitRemote( - repos, - this._options.remoteUrl! - ); - - // Check fetch and push by NodeGit.Remote - const remoteResult: 'exist' | 'create' = await this._checkFetch( - remote, - credentialCallbacks - ).catch(err => { - if ( - err instanceof Err.RemoteRepositoryNotFoundError && - this._options.connection?.type === 'github' - ) { - return 'create'; - } - - throw new Err.FetchConnectionFailedError(err.message); - }); - if (remoteResult === 'create') { - // Try to create repository by octokit - await this.create().catch(err => { - // App may check permission or - throw new Err.CannotCreateRemoteRepositoryError(err.message); - }); - } - - if (!onlyFetch) { - await this._checkPush(remote, credentialCallbacks).catch(err => { - throw new Err.PushConnectionFailedError(err.message); - }); - } - return [gitResult, remoteResult]; - } } diff --git a/src/remote/sync.ts b/src/remote/sync.ts index 51bbebf2..71b9c792 100644 --- a/src/remote/sync.ts +++ b/src/remote/sync.ts @@ -10,7 +10,11 @@ * ! Must import both clearInterval and setInterval from 'timers' */ import { clearInterval, setInterval } from 'timers'; -import nodegit from '@sosuisen/nodegit'; +import crypto from 'crypto'; +import git from 'isomorphic-git'; +import fs from 'fs-extra'; +import { name as default_engine_name } from '../plugin/remote-isomorphic-git'; + import { CONSOLE_STYLE, sleep } from '../utils'; import { Err } from '../error'; import { @@ -28,6 +32,7 @@ import { SyncRemoteChangeCallback, SyncResult, SyncResultCancel, + SyncResultNop, SyncResultPush, SyncResumeCallback, SyncStartCallback, @@ -38,9 +43,7 @@ import { SyncInterface } from '../types_sync'; import { GitDDBInterface } from '../types_gitddb'; import { syncWorker } from './sync_worker'; import { pushWorker } from './push_worker'; -import { createCredential } from './authentication'; import { RemoteRepository } from './remote_repository'; -import { checkHTTP } from './net'; import { DEFAULT_COMBINE_DB_STRATEGY, DEFAULT_CONFLICT_RESOLUTION_STRATEGY, @@ -48,25 +51,79 @@ import { MINIMUM_SYNC_INTERVAL, NETWORK_RETRY, NETWORK_RETRY_INTERVAL, - NETWORK_TIMEOUT, } from '../const'; import { JsonDiff } from './json_diff'; import { JsonPatchOT } from './json_patch_ot'; import { combineDatabaseWithTheirs } from './combine'; import { Validator } from '../validator'; +import { RemoteEngine, RemoteErr, wrappingRemoteEngineError } from './remote_engine'; + +/** + * encodeToGitRemoteName + * + * @remarks + * The first default name of Git remote is "origin". + * + * GitDocumentDB adds an alias of "origin", + * whose name is generated automatically by this function. + * The second and subsequent remotes are also named in the same way. + * + * A remote name consists of [remote address]_[hash]. + * Periods are replaced with underscores. + * e.g.) github_com_a0b1c23 + * It is human-readable. + * + * [remote address] is [hostname + domain name] or [ip address]. + * [hash] is calculated from remoteURL. + * + * [hash] is the first seven characters of SHA-1 so that it may collide. + * Capitalize one of the remote addresses when hashes collide + * because a hostname and a domain name are not case sensitive. + * + * @throws {@link RemoteErr.InvalidURLFormatError} + * + * @public + */ +export function encodeToGitRemoteName (remoteURL: string) { + let host: string; + if (/:\/\/.+?@(.+?):/.test(remoteURL)) { + // ssh://user@foo.bar:xxx/path/repos.git + host = RegExp.$1; + } + else if (/:\/\/(.+?):/.test(remoteURL)) { + // http://foo.bar:xxx/path/repos.git + host = RegExp.$1; + } + else if (/:\/\/.+?@(.+?)\//.test(remoteURL)) { + // ssh://user@foo.bar/path/repos.git + host = RegExp.$1; + } + else if (/:\/\/(.+?)\//.test(remoteURL)) { + // http://foo.bar/user/repos.git + host = RegExp.$1; + } + else if (/^.+?@(.+?):/.test(remoteURL)) { + // user@foo.bar:path/repos.git + host = RegExp.$1; + } + else { + throw new RemoteErr.InvalidURLFormatError(`URL format is invalid: ${remoteURL}`); + } + + const shortHash = crypto.createHash('sha1').update(remoteURL).digest('hex').substr(0, 7); + + // Use toLowerCase() because git.setConfig() and git.addRemote() automatically converts the path to lowercase. + return host.toLowerCase().replace(/\./g, '_') + '_' + shortHash; +} /** * Implementation of GitDocumentDB#sync(options, get_sync_result) * - * @throws {@link Err.RepositoryNotFoundError} - * @throws {@link Err.UndefinedRemoteURLError} (from Sync#constructor()) - * @throws {@link Err.IntervalTooSmallError} (from Sync#constructor()) + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} * - * @throws {@link Err.RemoteRepositoryConnectError} (from Sync#init()) - * @throws {@link Err.PushWorkerError} (from Sync#init()) - * @throws {@link Err.SyncWorkerError} (from Sync#init()) - * @throws {@link Err.NoMergeBaseFoundError} - * @throws {@link Err.PushNotAllowedError} (from Sync#init()) + * @throws # Errors from constructor of {@link Sync} class. + * @throws # Errors from {@link Sync.init} * * @internal */ @@ -74,26 +131,25 @@ export async function syncAndGetResultImpl ( this: GitDDBInterface, options: RemoteOptions ): Promise<[Sync, SyncResult]> { - const repos = this.repository(); - if (repos === undefined) { - throw new Err.RepositoryNotOpenError(); + if (this.isClosing) { + throw new Err.DatabaseClosingError(); } + if (!this.isOpened) { + return Promise.reject(new Err.RepositoryNotOpenError()); + } + const sync = new Sync(this, options); - const syncResult = await sync.init(repos); + const syncResult = await sync.init(); return [sync, syncResult]; } /** * Implementation of GitDocumentDB#sync(options) * - * @throws {@link Err.RepositoryNotFoundError} - * @throws {@link Err.UndefinedRemoteURLError} (from Sync#constructor()) - * @throws {@link Err.IntervalTooSmallError} (from Sync#constructor()) + * @throws {@link Err.DatabaseClosingError} + * @throws {@link Err.RepositoryNotOpenError} * - * @throws {@link Err.RemoteRepositoryConnectError} (from Sync#init()) - * @throws {@link Err.PushWorkerError} (from Sync#init()) - * @throws {@link Err.SyncWorkerError} (from Sync#init()) - * @throws {@link Err.NoMergeBaseFoundError} - * @throws {@link Err.PushNotAllowedError} (from Sync#init()) + * @throws # Errors from constructor of {@link Sync} class. + * @throws # Errors from {@link Sync.init} * * @internal */ @@ -101,16 +157,13 @@ export async function syncImpl ( this: GitDDBInterface, options: RemoteOptions ): Promise { - const repos = this.repository(); - if (repos === undefined) { - throw new Err.RepositoryNotOpenError(); - } - const sync = new Sync(this, options); - await sync.init(repos); + const [sync, syncResult] = await syncAndGetResultImpl.call(this, options); return sync; } /** + * Filter file changes by collectionPath + * * @internal */ function filterChanges (syncResult: SyncResult, collectionPath: string): SyncResult { @@ -178,10 +231,13 @@ function filterChanges (syncResult: SyncResult, collectionPath: string): SyncRes * @public */ export class Sync implements SyncInterface { + /********************************************** + * Private properties + ***********************************************/ private _gitDDB: GitDDBInterface; - private _checkoutOptions: nodegit.CheckoutOptions; private _syncTimer: NodeJS.Timeout | undefined; private _retrySyncCounter = 0; // Decremental count + private _isClosed = false; /*********************************************** * Public properties (readonly) @@ -197,6 +253,14 @@ export class Sync implements SyncInterface { return this._options.remoteUrl!; } + /** + * Remote Engine + */ + private _engine = default_engine_name; + get engine (): string { + return this._engine; + } + private _remoteRepository: RemoteRepository; /** * Remote repository @@ -222,21 +286,29 @@ export class Sync implements SyncInterface { return newOptions; } - private _upstreamBranch = ''; + private _remoteName = ''; /** - * upstreamBranch + * remoteName * * @readonly * @public */ - get upstreamBranch (): string { - return this._upstreamBranch; + get remoteName (): string { + return this._remoteName; } /*********************************************** * Public properties ***********************************************/ + /** + * runBeforeLiveSync + * + * This function is executed just before each automated(live) synchronization event is queued. + * Set undefined to stop it. + */ + public runBeforeLiveSync: (() => void) | undefined = undefined; + /** * SyncEvent handlers * @@ -264,13 +336,6 @@ export class Sync implements SyncInterface { error: [], }; - /** - * Callback for authentication - * - * @public - */ - credentialCallbacks: { [key: string]: any }; - /** * JsonDiff * @@ -290,10 +355,14 @@ export class Sync implements SyncInterface { * * @throws {@link Err.UndefinedRemoteURLError} * @throws {@link Err.IntervalTooSmallError} - * @throws {@link Err.InvalidAuthenticationTypeError} + * @throws {@link Err.SyncIntervalLessThanOrEqualToRetryIntervalError} + * + * @throws # Errors from encodeToGitRemoteName + * @throws - {@link RemoteErr.InvalidURLFormatError} * * @public */ + // eslint-disable-next-line complexity constructor (gitDDB: GitDDBInterface, options?: RemoteOptions) { this._gitDDB = gitDDB; @@ -315,10 +384,6 @@ export class Sync implements SyncInterface { this._options.conflictResolutionStrategy = options.conflictResolutionStrategy; if (this._options.remoteUrl === undefined || this._options.remoteUrl === '') { - /** - * TODO: Check upstream branch of this repository - * Set remoteUrl to the upstream branch and cloneRepository() if exists. - */ throw new Err.UndefinedRemoteURLError(); } @@ -343,100 +408,236 @@ export class Sync implements SyncInterface { this._options.conflictResolutionStrategy ??= DEFAULT_CONFLICT_RESOLUTION_STRATEGY; this.jsonDiff = new JsonDiff(gitDDB.schema.json); - this.jsonPatch = new JsonPatchOT(); + this.jsonPatch = new JsonPatchOT(gitDDB.schema.json); - this.credentialCallbacks = createCredential(this._options); - - this._upstreamBranch = `origin/${this._gitDDB.defaultBranch}`; - - this._checkoutOptions = new nodegit.CheckoutOptions(); - // nodegit.Checkout.STRATEGY.USE_OURS: For unmerged files, checkout stage 2 from index - this._checkoutOptions.checkoutStrategy = - nodegit.Checkout.STRATEGY.FORCE | nodegit.Checkout.STRATEGY.USE_OURS; + this._options.connection ??= { type: 'none' }; + this._options.connection.engine ??= default_engine_name; this._remoteRepository = new RemoteRepository({ remoteUrl: this._options.remoteUrl, connection: this._options.connection, }); - } - /*********************************************** - * Private properties - ***********************************************/ + this._remoteName = encodeToGitRemoteName(this.remoteURL); - /** - * Check network connection - * - * @internal - */ - async canNetworkConnection (): Promise { - const okOrNetworkError = await checkHTTP( - this._options.remoteUrl!, - NETWORK_TIMEOUT - ).catch(() => { - return { ok: false }; - }); - return okOrNetworkError.ok; + this._engine = this._options.connection.engine; } /*********************************************** - * Public properties + * Public methods ***********************************************/ /** - * Create remote connection + * Initialize remote connection * * @remarks * Call init() once just after creating an instance. * - * @throws {@link Err.RemoteRepositoryConnectError} - * @throws {@link Err.PushWorkerError} - * @throws {@link Err.NoMergeBaseFoundError} - * @throws {@link Err.SyncWorkerError} + * @throws {@link Err.CannotCreateRemoteRepositoryError} + * + * @throws # Errors from RemoteEngine[engineName].checkFetch + * @throws - {@link RemoteErr.InvalidGitRemoteError} + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.NetworkError} + * @throws - {@link RemoteErr.HTTPError401AuthorizationRequired} + * @throws - {@link RemoteErr.HTTPError404NotFound} + * @throws - {@link RemoteErr.CannotConnectError} + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.InvalidRepositoryURLError} + * @throws - {@link RemoteErr.InvalidSSHKeyPathError} + * @throws - {@link RemoteErr.InvalidAuthenticationTypeError} + * + * @throws Errors from {@link Sync.trySync} + * @throws Errors from {@link Sync.tryPush} * * @public */ - async init (repos: nodegit.Repository): Promise { - const onlyFetch = this._options.syncDirection === 'pull'; - const [gitResult, remoteResult] = await this.remoteRepository - .connect(this._gitDDB.repository()!, this.credentialCallbacks, onlyFetch) - .catch(err => { - throw new Err.RemoteRepositoryConnectError(err.message); + // eslint-disable-next-line complexity + async init (): Promise { + this._isClosed = false; + let isNewRemoteRepository = false; + + const urlOfRemote = await git.getConfig({ + fs, + dir: this._gitDDB.workingDir, + path: `remote.${this.remoteName}.url`, + }); + if (urlOfRemote !== this.remoteURL) { + await git.addRemote({ + fs, + dir: this._gitDDB.workingDir, + remote: this.remoteName, + url: this.remoteURL, + }); + } + + /** + * Set origin if not exist + */ + const originUrl = await git.getConfig({ + fs, + dir: this._gitDDB.workingDir, + path: `remote.origin.url`, + }); + if (originUrl === undefined) { + await git.addRemote({ + fs, + dir: this._gitDDB.workingDir, + remote: 'origin', + url: this.remoteURL, }); - this._gitDDB.logger.debug('git remote: ' + gitResult); - this._gitDDB.logger.debug('remote repository: ' + remoteResult); - if (remoteResult === 'create') { - this._upstreamBranch = ''; } + + let remoteResult: boolean | Error; + if (this._options.syncDirection === 'push') { + // checkFetch will return undefined if succeeds. + + // Do not download remote. + // eslint-disable-next-line no-await-in-loop + remoteResult = await RemoteEngine[this._engine] + .checkFetch( + this._gitDDB.workingDir, + this._options, + this.remoteName, + this._gitDDB.tsLogger + ) + .catch(err => err); + } + else { + // fetch will return true if succeeds. + + // eslint-disable-next-line no-await-in-loop + remoteResult = await RemoteEngine[this._engine] + .fetch( + this._gitDDB.workingDir, + this._options, + this.remoteName, + this._gitDDB.defaultBranch, + this._gitDDB.defaultBranch, + this._gitDDB.tsLogger + ) + .catch(err => err); + } + + /** + * Do not use 'instanceof' to compare git-documentdb-remote-errors + * because an error from RemoteEngine plugin may not have the same prototype + * in its prototype chain. + * - https://nodejs.org/en/blog/npm/peer-dependencies/ + * - https://stackoverflow.com/questions/46618852/require-and-instanceof/46630766 + * Use name property instead. + */ + if (typeof remoteResult === 'boolean' || remoteResult === undefined) { + // nop + } + else if (remoteResult.name === 'InvalidGitRemoteError') { + // checkFetch hardly invoke this error because checkFetch is called just after addRemote. + throw wrappingRemoteEngineError(remoteResult); + } + else if ( + remoteResult.name === 'InvalidURLFormatError' || + remoteResult.name === 'InvalidRepositoryURLError' || + remoteResult.name === 'InvalidSSHKeyPathError' || + remoteResult.name === 'InvalidAuthenticationTypeError' || + remoteResult.name === 'HTTPError401AuthorizationRequired' || + remoteResult.name === 'NetworkError' || + remoteResult.name === 'CannotConnectError' + ) { + throw wrappingRemoteEngineError(remoteResult); + } + else if (remoteResult.name === 'HTTPError404NotFound') { + // Try to create repository by octokit + // eslint-disable-next-line no-await-in-loop + await this.remoteRepository.create().catch(err => { + throw new Err.CannotCreateRemoteRepositoryError(err.message); + }); + isNewRemoteRepository = true; + } + let syncResult: SyncResult = { action: 'nop', }; - if (this._options === 'pull') { + if (this._options.syncDirection === 'pull') { + // Do not create a new remote repository because the direction is 'pull'. /** * TODO: Implement case when sync_direction is 'pull'. */ } - else if (this.upstreamBranch === '') { - this._gitDDB.logger.debug('upstream_branch is empty. tryPush..'); - // Empty upstream_branch shows that an empty repository has been created on a remote site. - // _trySync() pushes local commits to the remote branch. - syncResult = await this.tryPush(); - - // An upstream branch must be set to a local branch after the first push - // because refs/remotes/origin/main is not created until the first push. - await nodegit.Branch.setUpstream( - await repos.getBranch(this._gitDDB.defaultBranch), - `origin/${this._gitDDB.defaultBranch}` - ); - this._upstreamBranch = `origin/${this._gitDDB.defaultBranch}`; + else { + // push or both + if (this._options.syncDirection === 'both') { + // Check remote branch after fetching. + const remoteCommitOid = await git + .resolveRef({ + fs, + dir: this._gitDDB.workingDir, + ref: `refs/remotes/${this.remoteName}/${this._gitDDB.defaultBranch}`, + }) + .catch(() => undefined); + if (remoteCommitOid === undefined) { + // Remote repository is empty. + isNewRemoteRepository = true; + } + } + if (isNewRemoteRepository) { + this._gitDDB.logger.debug('upstream branch is not set yet. tryPush..'); + + // Remote repository may not be created yet due to internal delay of GitHub. + // Retry if not exist. + for (let i = 0; i < this._options.retry! + 1; i++) { + // eslint-disable-next-line no-await-in-loop + const syncResultOrError = await this.tryPush().catch(err => err); + if (syncResultOrError instanceof Error) { + if (syncResultOrError instanceof RemoteErr.HTTPError404NotFound) { + // eslint-disable-next-line no-await-in-loop + await sleep(this._options.retryInterval!); + if (i === this._options.retry!) { + throw syncResultOrError; + } + continue; + } + throw syncResultOrError; + } + syncResult = syncResultOrError; + break; + } + } + else if (this._options.syncDirection === 'push') { + this._gitDDB.logger.debug('upstream_branch exists. tryPush..'); + syncResult = await this.tryPush(); + } + else if (this._options.syncDirection === 'both') { + this._gitDDB.logger.debug('upstream_branch exists. trySync..'); + syncResult = await this.trySync(); + } } - else if (this._options.syncDirection === 'push') { - this._gitDDB.logger.debug('upstream_branch exists. tryPush..'); - syncResult = await this.tryPush(); + + const branchRemote = await git.getConfig({ + fs, + dir: this._gitDDB.workingDir, + path: `branch.${this._gitDDB.defaultBranch}.remote`, + }); + if (branchRemote === undefined) { + await git.setConfig({ + fs, + dir: this._gitDDB.workingDir, + path: `branch.${this._gitDDB.defaultBranch}.remote`, + value: this.remoteName, + }); } - else if (this._options.syncDirection === 'both') { - this._gitDDB.logger.debug('upstream_branch exists. trySync..'); - syncResult = await this.trySync(); + + const branchMerge = await git.getConfig({ + fs, + dir: this._gitDDB.workingDir, + path: `branch.${this._gitDDB.defaultBranch}.merge`, + }); + if (branchMerge === undefined) { + await git.setConfig({ + fs, + dir: this._gitDDB.workingDir, + path: `branch.${this._gitDDB.defaultBranch}.merge`, + value: `refs/heads/${this._gitDDB.defaultBranch}`, + }); } if (this._options.live) { @@ -445,7 +646,19 @@ export class Sync implements SyncInterface { listener.func(); }); this._syncTimer = setInterval(() => { - this.trySync().catch(() => undefined); + if (this.runBeforeLiveSync !== undefined) { + try { + this.runBeforeLiveSync(); + } catch (e) { + this._gitDDB.logger.debug('Error in runBeforeLiveSync: ' + e); + } + } + if (this._options.syncDirection === 'push') { + this.tryPushImpl(true).catch(() => undefined); + } + else if (this._options.syncDirection === 'both') { + this.trySyncImpl(true).catch(() => undefined); + } }, this._options.interval!); } } @@ -484,6 +697,7 @@ export class Sync implements SyncInterface { * @public */ resume (options?: { interval?: number; retry?: number }) { + if (this._isClosed) return false; if (this._options.live) return false; options ??= { @@ -502,12 +716,15 @@ export class Sync implements SyncInterface { this._options.retry = options.retry; } - if (this._gitDDB.repository() !== undefined) { - this._options.live = true; - this._syncTimer = setInterval(() => { - this.trySync().catch(() => undefined); - }, this._options.interval!); - } + this._options.live = true; + this._syncTimer = setInterval(() => { + if (this._options.syncDirection === 'push') { + this.tryPushImpl(true).catch(() => undefined); + } + else if (this._options.syncDirection === 'both') { + this.trySyncImpl(true).catch(() => undefined); + } + }, this._options.interval!); this.eventHandlers.resume.forEach(listener => { listener.func(); @@ -522,6 +739,7 @@ export class Sync implements SyncInterface { * @public */ close () { + this._isClosed = true; this.pause(); this.eventHandlers = { change: [], @@ -537,96 +755,224 @@ export class Sync implements SyncInterface { } /** - * Try to push with retries + * Try to push + * + * @throws {@link Err.PushNotAllowedError} + * + * @throws # Errors from push + * @throws - {@link RemoteErr.InvalidGitRemoteError} + * @throws - {@link RemoteErr.UnfetchedCommitExistsError} + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.NetworkError} + * @throws - {@link RemoteErr.HTTPError401AuthorizationRequired} + * @throws - {@link RemoteErr.HTTPError404NotFound} + * @throws - {@link RemoteErr.HTTPError403Forbidden} + * @throws - {@link RemoteErr.CannotConnectError} + * @throws - {@link RemoteErr.UnfetchedCommitExistsError} + * @throws - {@link RemoteErr.CannotConnectError} + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.InvalidRepositoryURLError} + * @throws - {@link RemoteErr.InvalidSSHKeyPathError} + * @throws - {@link RemoteErr.InvalidAuthenticationTypeError} * - * @throws {@link Err.PushNotAllowedError} (from this and enqueuePushTask) - * @throws {@link Err.PushWorkerError} (from this and enqueuePushTask) - * @throws {@link Err.UnfetchedCommitExistsError} (from this and enqueuePushTask) + * @throws # Errors from getChanges + * @throws - {@link Err.InvalidJsonObjectError} * * @public */ + async tryPush (): Promise { + return await this.tryPushImpl(false); + } + + /** + * tryPushImpl + * + * @internal + */ // eslint-disable-next-line complexity - async tryPush (): Promise { + async tryPushImpl ( + calledAsPeriodicTask: boolean + ): Promise { + if (this._isClosed) return { action: 'canceled' }; if (this._options.syncDirection === 'pull') { throw new Err.PushNotAllowedError(this._options.syncDirection); } - if (this._retrySyncCounter === 0) { - this._retrySyncCounter = this._options.retry! + 1; - } - - while (this._retrySyncCounter > 0) { - // eslint-disable-next-line no-await-in-loop - const resultOrError = await this.enqueuePushTask().catch((err: Error) => err); - let error: Error | undefined; - let result: SyncResultPush | SyncResultCancel | undefined; - if (resultOrError instanceof Error) { - error = resultOrError; - } - else { - result = resultOrError; + /** + * Enqueue pushWorker + */ + const taskId = this._gitDDB.taskQueue.newTaskId(); + const callback = ( + resolve: (value: SyncResultPush | SyncResultCancel | SyncResultNop) => void, + reject: (reason: any) => void + ) => ( + beforeResolve: () => void, + beforeReject: () => void, + taskMetadata: TaskMetadata + ) => { + if (calledAsPeriodicTask && !this._options.live) { + return Promise.resolve().then(() => { + const resultCancel: SyncResultCancel = { + action: 'canceled', + }; + beforeResolve(); + resolve(resultCancel); + }); } + return pushWorker(this._gitDDB, this, taskMetadata) + .then((syncResultPush: SyncResultPush | SyncResultNop) => { + this._gitDDB.logger.debug( + `pushWorker: ${JSON.stringify(syncResultPush)}`, + CONSOLE_STYLE.bgWhite().fgBlack().tag + ); - if (error instanceof Err.UnfetchedCommitExistsError) { - if (this._options.syncDirection === 'push') { - if (this._options.combineDbStrategy === 'replace-with-ours') { - // TODO: Exec replace-with-ours instead of throw error + if (syncResultPush.action === 'push') { + this.eventHandlers.change.forEach(listener => { + const filteredSyncResultPush = filterChanges( + JSON.parse(JSON.stringify(syncResultPush)), + listener.collectionPath + ) as SyncResultPush; + listener.func(filteredSyncResultPush, { + ...taskMetadata, + collectionPath: listener.collectionPath, + }); + }); + + this.eventHandlers.remoteChange.forEach(listener => { + const filteredSyncResultPush = filterChanges( + JSON.parse(JSON.stringify(syncResultPush)), + listener.collectionPath + ) as SyncResultPush; + listener.func(filteredSyncResultPush.changes.remote, { + ...taskMetadata, + collectionPath: listener.collectionPath, + }); + }); } - else { - throw error; + + if (syncResultPush.action === 'push') { + this.eventHandlers.complete.forEach(listener => { + listener.func({ ...taskMetadata, collectionPath: listener.collectionPath }); + }); } - } - } - if (error) { - this._gitDDB.logger.debug('Push failed: ' + error.message); - this._retrySyncCounter--; - if (this._retrySyncCounter === 0) { - throw error; - } - } + beforeResolve(); + resolve(syncResultPush); + }) + .catch(err => { + // console.log(`Error in push_worker: ${err}`); + this.eventHandlers.error.forEach(listener => { + listener.func(err, { + ...taskMetadata, + collectionPath: listener.collectionPath, + }); + }); - if (result && result.action === 'canceled') { - return result; - } + beforeReject(); + reject(err); + }); + }; - if (error === undefined && result !== undefined) { - this._retrySyncCounter = 0; - return result; - } + const cancel = (resolve: (value: SyncResultCancel) => void) => () => { + const result: SyncResultCancel = { action: 'canceled' }; + this._gitDDB.logger.debug( + `pushWorker: ${JSON.stringify(result)}`, + CONSOLE_STYLE.bgWhite().fgBlack().tag + ); + resolve(result); + }; - // eslint-disable-next-line no-await-in-loop - if (!(await this.canNetworkConnection())) { - // Retry to connect due to network error. - this._gitDDB.logger.debug( - CONSOLE_STYLE.bgRed().tag()`...retryPush: ${this.currentRetries().toString()}` - ); - // eslint-disable-next-line no-await-in-loop - await sleep(this._options.retryInterval!); + const task = ( + resolve: (value: SyncResultPush | SyncResultCancel | SyncResultNop) => void, + reject: (reason: any) => void + ): Task => { + return { + label: 'push', + taskId: taskId!, + syncRemoteName: this.remoteName, + func: callback(resolve, reject), + cancel: cancel(resolve), + }; + }; + + const resultOrError = await new Promise( + ( + resolve: (value: SyncResultPush | SyncResultCancel | SyncResultNop) => void, + reject + ) => { + this._gitDDB.taskQueue.pushToTaskQueue(task(resolve, reject)); + // this._gitDDB.taskQueue.unshiftSyncTaskToTaskQueue(task(resolve, reject)); } - else { - this._retrySyncCounter = 0; - throw error; + ).catch((err: Error) => err); + + if (resultOrError instanceof Error) { + if (resultOrError instanceof RemoteErr.UnfetchedCommitExistsError) { + if (this._options.syncDirection === 'push') { + if (this._options.combineDbStrategy === 'replace-with-ours') { + // TODO: Exec replace-with-ours instead of throw error + } + } } + // Fatal error. Don't retry? + // this.pause(); + throw resultOrError; } - // This line is reached when cancel() set _retrySyncCounter to 0; - const cancel: SyncResultCancel = { action: 'canceled' }; - this._retrySyncCounter = 0; - return cancel; + + return resultOrError; } /** * Try to sync with retries * - * @throws {@link Err.PushNotAllowedError} (from this and enqueueSyncTask) - * @throws {@link Err.SyncWorkerError} (from enqueueSyncTask) - * @throws {@link Err.NoMergeBaseFoundError} (from enqueueSyncTask) - * @throws {@link Err.UnfetchedCommitExistsError} (from enqueueSyncTask) + * @throws {@link Err.PushNotAllowedError} + * @throws {@link Err.CombineDatabaseError} + * + * @throws # Errors from syncWorker + * @throws - {@link Err.NoMergeBaseFoundError} + * @throws - {@link Err.ThreeWayMergeError} + * @throws - {@link Err.CannotDeleteDataError} + * + * @throws # Errors from fetch, pushWorker + * @throws - {@link RemoteErr.InvalidGitRemoteError} + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.NetworkError} + * @throws - {@link RemoteErr.HTTPError401AuthorizationRequired} + * @throws - {@link RemoteErr.HTTPError404NotFound} + * @throws - {@link RemoteErr.CannotConnectError} + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.InvalidRepositoryURLError} + * @throws - {@link RemoteErr.InvalidSSHKeyPathError} + * @throws - {@link RemoteErr.InvalidAuthenticationTypeError} + * + * @throws # Errors from pushWorker + * @throws - {@link RemoteErr.HTTPError403Forbidden} + * @throws - {@link RemoteErr.UnfetchedCommitExistsError} + * + * @throws # Errors from merge + * @throws - {@link Err.InvalidConflictStateError} + * @throws - {@link Err.CannotDeleteDataError} + * @throws - {@link Err.InvalidDocTypeError} + * @throws - {@link Err.InvalidConflictResolutionStrategyError} + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws - {@link Err.InvalidJsonObjectError} + * + * @throws # Errors from getChanges + * @throws - {@link Err.InvalidJsonObjectError} * * @public */ - // eslint-disable-next-line complexity async trySync (): Promise { + return await this.trySyncImpl(false); + } + + /** + * trySyncImpl + * + * @internal + */ + // eslint-disable-next-line complexity + async trySyncImpl (calledAsPeriodicTask: boolean): Promise { + if (this._isClosed) return { action: 'canceled' }; if (this._options.syncDirection === 'pull') { throw new Err.PushNotAllowedError(this._options.syncDirection); } @@ -636,7 +982,9 @@ export class Sync implements SyncInterface { while (this._retrySyncCounter > 0) { // eslint-disable-next-line no-await-in-loop - const resultOrError = await this.enqueueSyncTask().catch((err: Error) => err); + const resultOrError = await this.enqueueSyncTask(calledAsPeriodicTask).catch( + (err: Error) => err + ); let error: Error | undefined; let result: SyncResult | undefined; @@ -656,294 +1004,194 @@ export class Sync implements SyncInterface { if (error instanceof Err.NoMergeBaseFoundError) { if (this._options.combineDbStrategy === 'throw-error') { - throw error; + // nop } else if (this._options.combineDbStrategy === 'combine-head-with-theirs') { // return SyncResultCombineDatabase // eslint-disable-next-line no-await-in-loop const syncResultCombineDatabase = await combineDatabaseWithTheirs( this._gitDDB, - this._options + this._options, + this.remoteName ).catch(err => { - throw new Err.CombineDatabaseError(err.message); + if (err) + // throw new Err.CombineDatabaseError(err.message); + error = new Err.CombineDatabaseError(err.message); + return undefined; }); - // eslint-disable-next-line no-loop-func - this.eventHandlers.combine.forEach(callback => - callback.func(syncResultCombineDatabase.duplicates) - ); - return syncResultCombineDatabase; + if (syncResultCombineDatabase !== undefined) { + // eslint-disable-next-line no-loop-func + this.eventHandlers.combine.forEach(callback => + callback.func(syncResultCombineDatabase.duplicates) + ); + return syncResultCombineDatabase; + } } } - if (error) { - this._gitDDB.logger.debug('Sync or push failed: ' + error.message); - this._retrySyncCounter--; - if (this._retrySyncCounter === 0) { + if (error !== undefined) { + this._gitDDB.logger.debug('trySync failed: ' + error.message); + if (error instanceof RemoteErr.UnfetchedCommitExistsError) { + this._retrySyncCounter--; + if (this._retrySyncCounter === 0) { + // this.pause(); + throw error; + } + this._gitDDB.logger.debug( + `...retrySync: ${this.currentRetries().toString()}`, + CONSOLE_STYLE.bgRed().tag + ); + // eslint-disable-next-line no-await-in-loop + await sleep(this._options.retryInterval!); + } + else { + // Throw error + this._retrySyncCounter = 0; + // this.pause(); throw error; } } - - if (result && result.action === 'canceled') { - return result; - } - - if (error === undefined && result !== undefined) { + else if (result !== undefined) { // No error this._retrySyncCounter = 0; return result; } - - if ( - // eslint-disable-next-line no-await-in-loop - !(await this.canNetworkConnection()) || - error instanceof Err.UnfetchedCommitExistsError - ) { - // Retry for the following reasons: - // - Network connection may be improved next time. - // - Problem will be resolved by sync again. - // - 'push' action throws UnfetchedCommitExistsError - // - push_worker in 'merge and push' action throws UnfetchedCommitExistsError - // - push_worker in 'resolve conflicts and push' action throws UnfetchedCommitExistsError - this._gitDDB.logger.debug( - CONSOLE_STYLE.bgRed().tag()`...retrySync: ${this.currentRetries().toString()}` - ); - // eslint-disable-next-line no-await-in-loop - await sleep(this._options.retryInterval!); - } - else { - // Throw error - this._retrySyncCounter = 0; - throw error; - } } // This line is reached when cancel() set _retrySyncCounter to 0; const cancel: SyncResultCancel = { action: 'canceled' }; + this._gitDDB.logger.debug( + `syncWorker: ${JSON.stringify(cancel)}`, + CONSOLE_STYLE.bgWhite().fgBlack().tag + ); this._retrySyncCounter = 0; return cancel; } /** - * Enqueue push task to TaskQueue - * - * @throws {@link Err.PushWorkerError} - * @throws {@link Err.UnfetchedCommitExistsError} - * @throws {@link Err.PushNotAllowedError} + * Enqueue sync task to TaskQueue * * @public */ - enqueuePushTask (): Promise { - if (this._options.syncDirection === 'pull') { - throw new Err.PushNotAllowedError(this._options.syncDirection); - } + enqueueSyncTask (calledAsPeriodicTask: boolean): Promise { const taskId = this._gitDDB.taskQueue.newTaskId(); const callback = ( - resolve: (value: SyncResultPush | SyncResultCancel) => void, + resolve: (value: SyncResult) => void, reject: (reason: any) => void ) => ( beforeResolve: () => void, beforeReject: () => void, taskMetadata: TaskMetadata - ) => - pushWorker(this._gitDDB, this, taskMetadata) - .then((syncResultPush: SyncResultPush) => { - this._gitDDB.logger.debug( - CONSOLE_STYLE.bgWhite().fgBlack().tag()`push_worker: ${JSON.stringify( - syncResultPush - )}` - ); - - this.eventHandlers.change.forEach(listener => { - const filteredSyncResultPush = filterChanges( - JSON.parse(JSON.stringify(syncResultPush)), - listener.collectionPath - ) as SyncResultPush; - listener.func(filteredSyncResultPush, { - ...taskMetadata, - collectionPath: listener.collectionPath, - }); - }); - if (syncResultPush.action === 'push') { - this.eventHandlers.remoteChange.forEach(listener => { - const filteredSyncResultPush = filterChanges( - JSON.parse(JSON.stringify(syncResultPush)), - listener.collectionPath - ) as SyncResultPush; - listener.func(filteredSyncResultPush.changes.remote, { - ...taskMetadata, - collectionPath: listener.collectionPath, - }); - }); - } - this.eventHandlers.complete.forEach(listener => { - listener.func({ ...taskMetadata, collectionPath: listener.collectionPath }); - }); - + ) => { + if (calledAsPeriodicTask && !this._options.live) { + return Promise.resolve().then(() => { + const resultCancel: SyncResultCancel = { + action: 'canceled', + }; beforeResolve(); - resolve(syncResultPush); - }) - .catch(err => { - // console.log(`Error in push_worker: ${err}`); - if (!(err instanceof Err.UnfetchedCommitExistsError)) { - err = new Err.PushWorkerError(err.message); - } - this.eventHandlers.error.forEach(listener => { - listener.func(err, { - ...taskMetadata, - collectionPath: listener.collectionPath, - }); - }); - - beforeReject(); - reject(err); + resolve(resultCancel); }); - - const cancel = (resolve: (value: SyncResultCancel) => void) => () => { - const result: SyncResultCancel = { action: 'canceled' }; - resolve(result); - }; - - const task = ( - resolve: (value: SyncResultPush | SyncResultCancel) => void, - reject: (reason: any) => void - ): Task => { - return { - label: 'push', - taskId: taskId!, - func: callback(resolve, reject), - cancel: cancel(resolve), - }; - }; - - return new Promise( - (resolve: (value: SyncResultPush | SyncResultCancel) => void, reject) => { - this._gitDDB.taskQueue.pushToTaskQueue(task(resolve, reject)); - // this._gitDDB.taskQueue.unshiftSyncTaskToTaskQueue(task(resolve, reject)); } - ); - } - - /** - * Enqueue sync task to TaskQueue - * - * @throws {@link Err.SyncWorkerError} - * @throws {@link Err.NoMergeBaseFoundError} - * @throws {@link Err.UnfetchedCommitExistsError} - * @throws {@link Err.PushNotAllowedError} - * - * @public - */ - enqueueSyncTask (): Promise { - if (this._options.syncDirection === 'pull') { - throw new Err.PushNotAllowedError(this._options.syncDirection); - } - const taskId = this._gitDDB.taskQueue.newTaskId(); - const callback = ( - resolve: (value: SyncResult) => void, - reject: (reason: any) => void - ) => ( - beforeResolve: () => void, - beforeReject: () => void, - taskMetadata: TaskMetadata - ) => - syncWorker(this._gitDDB, this, taskMetadata) - // eslint-disable-next-line complexity - .then(syncResult => { - this._gitDDB.logger.debug( - CONSOLE_STYLE.bgWhite().fgBlack().tag()`sync_worker: ${JSON.stringify( - syncResult - )}` - ); - - if ( - syncResult.action === 'resolve conflicts and push' || - syncResult.action === 'merge and push' || - syncResult.action === 'resolve conflicts and push error' || - syncResult.action === 'merge and push error' || - syncResult.action === 'fast-forward merge' || - syncResult.action === 'push' - ) { - this.eventHandlers.change.forEach(listener => { - let syncResultForChangeEvent = JSON.parse(JSON.stringify(syncResult)); - syncResultForChangeEvent = filterChanges( - syncResultForChangeEvent, - listener.collectionPath - ) as SyncResult; - listener.func(syncResultForChangeEvent, { - ...taskMetadata, - collectionPath: listener.collectionPath, + return ( + syncWorker(this._gitDDB, this, taskMetadata) + // eslint-disable-next-line complexity + .then((syncResult: SyncResult) => { + this._gitDDB.logger.debug( + `syncWorker: ${JSON.stringify(syncResult)}`, + CONSOLE_STYLE.bgWhite().fgBlack().tag + ); + + if ( + syncResult.action === 'resolve conflicts and push' || + syncResult.action === 'merge and push' || + syncResult.action === 'resolve conflicts and push error' || + syncResult.action === 'merge and push error' || + syncResult.action === 'fast-forward merge' || + syncResult.action === 'push' + ) { + this.eventHandlers.change.forEach(listener => { + let syncResultForChangeEvent = JSON.parse(JSON.stringify(syncResult)); + syncResultForChangeEvent = filterChanges( + syncResultForChangeEvent, + listener.collectionPath + ) as SyncResult; + + listener.func(syncResultForChangeEvent, { + ...taskMetadata, + collectionPath: listener.collectionPath, + }); }); - }); - } + } + + if ( + syncResult.action === 'resolve conflicts and push' || + syncResult.action === 'merge and push' || + syncResult.action === 'resolve conflicts and push error' || + syncResult.action === 'merge and push error' || + syncResult.action === 'fast-forward merge' + ) { + this.eventHandlers.localChange.forEach(listener => { + let syncResultForLocalChangeEvent = JSON.parse(JSON.stringify(syncResult)); + syncResultForLocalChangeEvent = filterChanges( + syncResultForLocalChangeEvent, + listener.collectionPath + ) as SyncResult; + listener.func(syncResultForLocalChangeEvent.changes.local, { + ...taskMetadata, + collectionPath: listener.collectionPath, + }); + }); + } + + if ( + syncResult.action === 'resolve conflicts and push' || + syncResult.action === 'merge and push' || + syncResult.action === 'push' + ) { + this.eventHandlers.remoteChange.forEach(listener => { + let syncResultForRemoteChangeEvent = JSON.parse(JSON.stringify(syncResult)); + syncResultForRemoteChangeEvent = filterChanges( + syncResultForRemoteChangeEvent, + listener.collectionPath + ) as SyncResult; + listener.func(syncResultForRemoteChangeEvent.changes.remote, { + ...taskMetadata, + collectionPath: listener.collectionPath, + }); + }); + } - if ( - syncResult.action === 'resolve conflicts and push' || - syncResult.action === 'merge and push' || - syncResult.action === 'resolve conflicts and push error' || - syncResult.action === 'merge and push error' || - syncResult.action === 'fast-forward merge' - ) { - this.eventHandlers.localChange.forEach(listener => { - let syncResultForLocalChangeEvent = JSON.parse(JSON.stringify(syncResult)); - syncResultForLocalChangeEvent = filterChanges( - syncResultForLocalChangeEvent, - listener.collectionPath - ) as SyncResult; - listener.func(syncResultForLocalChangeEvent.changes.local, { + this.eventHandlers.complete.forEach(listener => + listener.func({ ...taskMetadata, collectionPath: listener.collectionPath, - }); - }); - } - - if ( - syncResult.action === 'resolve conflicts and push' || - syncResult.action === 'merge and push' || - syncResult.action === 'push' - ) { - this.eventHandlers.remoteChange.forEach(listener => { - let syncResultForRemoteChangeEvent = JSON.parse(JSON.stringify(syncResult)); - syncResultForRemoteChangeEvent = filterChanges( - syncResultForRemoteChangeEvent, - listener.collectionPath - ) as SyncResult; - listener.func(syncResultForRemoteChangeEvent.changes.remote, { + }) + ); + + beforeResolve(); + resolve(syncResult); + }) + .catch((err: Error) => { + // console.log(`Error in syncWorker: ${err}`); + this.eventHandlers.error.forEach(listener => { + listener.func(err, { ...taskMetadata, collectionPath: listener.collectionPath, }); }); - } - this.eventHandlers.complete.forEach(listener => - listener.func({ ...taskMetadata, collectionPath: listener.collectionPath }) - ); - - beforeResolve(); - resolve(syncResult); - }) - .catch(err => { - // console.log(`Error in sync_worker: ${err}`); - if ( - !( - err instanceof Err.NoMergeBaseFoundError || - err instanceof Err.UnfetchedCommitExistsError - ) - ) { - err = new Err.SyncWorkerError(err.message); - } - this.eventHandlers.error.forEach(listener => { - listener.func(err, { - ...taskMetadata, - collectionPath: listener.collectionPath, - }); - }); - - beforeReject(); - reject(err); - }); + beforeReject(); + reject(err); + }) + ); + }; const cancel = (resolve: (value: SyncResultCancel) => void) => () => { const result: SyncResultCancel = { action: 'canceled' }; + this._gitDDB.logger.debug( + `syncWorker: ${JSON.stringify(result)}`, + CONSOLE_STYLE.bgWhite().fgBlack().tag + ); resolve(result); }; @@ -954,6 +1202,7 @@ export class Sync implements SyncInterface { return { label: 'sync', taskId: taskId!, + syncRemoteName: this.remoteName, func: callback(resolve, reject), cancel: cancel(resolve), }; @@ -961,7 +1210,6 @@ export class Sync implements SyncInterface { return new Promise((resolve: (value: SyncResult) => void, reject) => { this._gitDDB.taskQueue.pushToTaskQueue(task(resolve, reject)); - // this._gitDDB.taskQueue.unshiftSyncTaskToTaskQueue(task(resolve, reject)); }); } @@ -982,7 +1230,9 @@ export class Sync implements SyncInterface { * @eventProperty * @public */ + // eslint-disable-next-line complexity on (event: SyncEvent, callback: SyncCallback, collectionPath = '') { + if (this._isClosed) return this; collectionPath = Validator.normalizeCollectionPath(collectionPath); if (event === 'change') this.eventHandlers[event].push({ @@ -1040,6 +1290,7 @@ export class Sync implements SyncInterface { * @public */ off (event: SyncEvent, callback: SyncCallback) { + if (this._isClosed) return this; // @ts-ignore this.eventHandlers[event] = this.eventHandlers[event].filter( (listener: { collectionPath: string; func: (res?: any) => void }) => { diff --git a/src/remote/sync_worker.ts b/src/remote/sync_worker.ts index 8570b87d..de265c10 100644 --- a/src/remote/sync_worker.ts +++ b/src/remote/sync_worker.ts @@ -7,61 +7,64 @@ * found in the LICENSE file in the root directory of gitDDB source tree. */ -import nodePath from 'path'; -import nodegit from '@sosuisen/nodegit'; import git from 'isomorphic-git'; import fs from 'fs-extra'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../const'; -import { CONSOLE_STYLE, normalizeCommit, utf8decode } from '../utils'; -import { Err } from '../error'; +import { SHORT_SHA_LENGTH } from '../const'; +import { normalizeCommit } from '../utils'; import { GitDDBInterface } from '../types_gitddb'; import { - AcceptedConflict, NormalizedCommit, SyncResult, SyncResultMergeAndPush, SyncResultMergeAndPushError, + SyncResultPush, SyncResultResolveConflictsAndPush, SyncResultResolveConflictsAndPushError, TaskMetadata, } from '../types'; import { SyncInterface } from '../types_sync'; import { pushWorker } from './push_worker'; -import { calcDistance, getChanges, getCommitLogs, writeBlobToFile } from './worker_utils'; -import { threeWayMerge } from './3way_merge'; - -/** - * git fetch - * - * @throws {@link Err.SyncWorkerFetchError} - */ -async function fetch (gitDDB: GitDDBInterface, sync: SyncInterface) { - gitDDB.logger.debug( - CONSOLE_STYLE.bgWhite().fgBlack().tag()`sync_worker: fetch: ${sync.remoteURL}` - ); - await gitDDB - .repository()! - .fetch('origin', { - callbacks: sync.credentialCallbacks, - }) - .catch(err => { - throw new Err.SyncWorkerFetchError(err.message); - }); -} +import { calcDistance, getAndWriteLocalChanges, getCommitLogs } from './worker_utils'; +import { merge } from './3way_merge'; +import { RemoteEngine, wrappingRemoteEngineError } from './remote_engine'; +import { Err } from '../error'; /** * sync_worker * - * @throws {@link Err.RepositoryNotOpenError} (from this and push_worker()) - * @throws {@link Err.SyncWorkerFetchError} (from fetch() and push_worker()) * @throws {@link Err.NoMergeBaseFoundError} * @throws {@link Err.ThreeWayMergeError} * @throws {@link Err.CannotDeleteDataError} - * @throws {@link Err.InvalidJsonObjectError} (from getChanges()) - * @throws {@link Err.UnfetchedCommitExistsError} (from push_worker()) - * @throws {@link Err.InvalidJsonObjectError} (from push_worker()) - * @throws {@link Err.GitPushError} (from push_worker()) - * @throws {@link Err.GitMergeBranchError} (from NodeGit.repos.mergeBranches()) + * + * @throws # Errors from fetch, pushWorker + * @throws - {@link RemoteErr.InvalidGitRemoteError} + * @throws - {@link RemoteErr.InvalidURLFormatError} + * @throws - {@link RemoteErr.NetworkError} + * @throws - {@link RemoteErr.HTTPError401AuthorizationRequired} + * @throws - {@link RemoteErr.HTTPError404NotFound} + * @throws - {@link RemoteErr.CannotConnectError} + * @throws - {@link RemoteErr.HttpProtocolRequiredError} + * @throws - {@link RemoteErr.InvalidRepositoryURLError} + * @throws - {@link RemoteErr.InvalidSSHKeyPathError} + * @throws - {@link RemoteErr.InvalidAuthenticationTypeError} + * + * @throws # Errors from pushWorker + * @throws - {@link RemoteErr.HTTPError403Forbidden} + * @throws - {@link RemoteErr.UnfetchedCommitExistsError} + * + * @throws # Errors from merge + * @throws - {@link Err.InvalidConflictStateError} + * @throws - {@link Err.CannotDeleteDataError} + * @throws ## Errors from getMergedDocument + * @throws - {@link Err.InvalidDocTypeError} + * @throws - {@link Err.InvalidConflictResolutionStrategyError} + * @throws ## Errors from writeBlobToFile + * @throws - {@link Err.CannotCreateDirectoryError} + * @throws ## Errors from getFatDocFromData, getFatDocFromReadBlobResult + * @throws - {@link Err.InvalidJsonObjectError} + * + * @throws # Errors from getChanges + * @throws - {@link Err.InvalidJsonObjectError} * * @internal */ @@ -71,10 +74,7 @@ export async function syncWorker ( sync: SyncInterface, taskMetadata: TaskMetadata ): Promise { - const repos = gitDDB.repository(); - if (repos === undefined) { - throw new Err.RepositoryNotOpenError(); - } + const syncOptions = sync.options; sync.eventHandlers.start.forEach(listener => { listener.func( { ...taskMetadata, collectionPath: listener.collectionPath }, @@ -85,7 +85,18 @@ export async function syncWorker ( /** * Fetch */ - await fetch(gitDDB, sync); + await RemoteEngine[sync.engine] + .fetch( + gitDDB.workingDir, + syncOptions, + sync.remoteName, + gitDDB.defaultBranch, + gitDDB.defaultBranch, + gitDDB.tsLogger + ) + .catch(err => { + throw wrappingRemoteEngineError(err); + }); /** * Calc distance @@ -95,174 +106,110 @@ export async function syncWorker ( dir: gitDDB.workingDir, ref: 'HEAD', }); + const oldRemoteCommitOid = await git.resolveRef({ fs, dir: gitDDB.workingDir, - ref: 'refs/remotes/origin/main', + ref: `refs/remotes/${sync.remoteName}/${gitDDB.defaultBranch}`, + }); + + const [baseCommitOid] = await git.findMergeBase({ + fs, + dir: gitDDB.workingDir, + oids: [oldCommitOid, oldRemoteCommitOid], }); - const distance = await calcDistance(gitDDB.workingDir, oldCommitOid, oldRemoteCommitOid); + + const distance = await calcDistance(baseCommitOid, oldCommitOid, oldRemoteCommitOid); // ahead: 0, behind 0 => Nothing to do: Local does not have new commits. Remote has not pushed new commits. // ahead: 0, behind 1 => Fast-forward merge : Local does not have new commits. Remote has pushed new commits. // ahead: 1, behind 0 => Push : Local has new commits. Remote has not pushed new commits. // ahead: 1, behind 1 => Merge, may resolve conflict and push: Local has new commits. Remote has pushed new commits. - let conflictedIndex: nodegit.Index | undefined; - let newCommitOid: nodegit.Oid | string | undefined; - if (distance.ahead === 0 && distance.behind === 0) { + if (distance.ahead === undefined || distance.behind === undefined) { + throw new Err.NoMergeBaseFoundError(); + } + else if (distance.ahead === 0 && distance.behind === 0) { return { action: 'nop' }; } else if (distance.ahead === 0 && distance.behind > 0) { - newCommitOid = await repos - .mergeBranches(gitDDB.defaultBranch, `origin/${gitDDB.defaultBranch}`) - .catch((res: nodegit.Index) => { - /* returns conflicted index */ conflictedIndex = res; - return undefined; - }); - } - else if (distance.ahead > 0 && distance.behind > 0) { - newCommitOid = await repos - .mergeBranches(gitDDB.defaultBranch, `origin/${gitDDB.defaultBranch}`) - .catch((res: nodegit.Index) => { - // Exception locks files. Try cleanup - repos.cleanup(); - - if (res instanceof Error) { - if (res.message.startsWith('no merge base found')) { - throw new Err.NoMergeBaseFoundError(); - } - throw new Err.GitMergeBranchError(res.message); - } - /* returns conflicted index */ conflictedIndex = res; - return undefined; - }); - } - else if (distance.ahead > 0 && distance.behind === 0) { - // Push - return await pushWorker(gitDDB, sync, taskMetadata, true).catch(err => { - throw err; + /** + * Fast forward + */ + await git.writeRef({ + fs, + dir: gitDDB.workingDir, + ref: 'refs/heads/' + gitDDB.defaultBranch, + value: oldRemoteCommitOid, + force: true, }); - } - - if (newCommitOid instanceof nodegit.Oid) { - newCommitOid = newCommitOid.tostrS(); - } - - if (conflictedIndex === undefined) { - // Conflict has not been occurred. - // Exec fast-forward or normal merge. + const newCommitOid = oldRemoteCommitOid; - // When a local file is removed and the same remote file is removed, - // they cannot be merged by fast-forward. They are merged as usual. - const distanceAgain = await calcDistance( + const localChanges = await getAndWriteLocalChanges( gitDDB.workingDir, + oldCommitOid, newCommitOid!, - await git.resolveRef({ - fs, - dir: gitDDB.workingDir, - ref: 'refs/remotes/origin/main', - }) + gitDDB.serializeFormat ); - if (distanceAgain.ahead === 0) { - const localChanges = await getChanges(gitDDB.workingDir, oldCommitOid, newCommitOid!); + const syncResultFastForwardMerge: SyncResult = { + action: 'fast-forward merge', + changes: { + local: localChanges, + }, + }; - const syncResultFastForwardMerge: SyncResult = { - action: 'fast-forward merge', - changes: { - local: localChanges, - }, + if (syncOptions.includeCommits) { + // Get list of commits which has been merged to local + const commitsFromRemote = await getCommitLogs( + gitDDB.workingDir, + oldRemoteCommitOid, + oldCommitOid + ); + syncResultFastForwardMerge.commits = { + local: commitsFromRemote, }; - - if (sync.options.includeCommits) { - // Get list of commits which has been merged to local - const commitsFromRemote = await getCommitLogs( - gitDDB.workingDir, - oldRemoteCommitOid, - oldCommitOid - ); - syncResultFastForwardMerge.commits = { - local: commitsFromRemote, - }; - } - return syncResultFastForwardMerge; } - - // distance_again.ahead > 0 - - // This case is occurred when not fast-forward. - // - insert/update a remote file, and insert/update another local file - // - insert/update a remote file, and insert/update the same local file with the same contents - // - insert/update a remote file, and remove another local file - // - remove a remote file, and insert/update another local file - // - remove a remote file, and remove the same local file - - // Compare trees before and after merge - const currentIndex = await repos.refreshIndex(); - - const localChanges = await getChanges(gitDDB.workingDir, oldCommitOid, newCommitOid!); + return syncResultFastForwardMerge; + } + else if (distance.ahead > 0 && distance.behind === 0) { /** - * Repository.mergeBranches does not handle updating and deleting file. - * So a file updated/deleted on remote side is not applied to - * on both local filesystem and local index. - * Change them by hand. + * Push */ - // Cannot use await in forEach. Use for-of. - for (const change of localChanges) { - if (change.operation === 'delete') { - const filename = change.old._id + JSON_EXT; - const path = nodePath.resolve(repos.workdir(), filename); - await fs.remove(path).catch(() => { - throw new Err.CannotDeleteDataError(); - }); - await currentIndex.removeByPath(filename); - } - else if (change.operation === 'update') { - const filename = change.old._id + JSON_EXT; - const { blob } = await git.readBlob({ - fs, - dir: gitDDB.workingDir, - oid: change.old._id, - }); - const data = utf8decode(blob); - await writeBlobToFile(gitDDB, filename, data); - await currentIndex.addByPath(filename); - } - } + return await pushWorker(gitDDB, sync, taskMetadata, true).catch(err => { + throw err; + }); + } - await currentIndex.write(); + /** + * Merge (distance.ahead > 0 && distance.behind > 0) + */ + const [mergedTreeOid, localChanges, remoteChanges, acceptedConflicts] = await merge( + gitDDB, + sync, + baseCommitOid, + oldCommitOid, + oldRemoteCommitOid + ); - /** - * Amend (move HEAD and commit again) - */ - const newCommit = await git.readCommit({ - fs, - dir: gitDDB.workingDir, - oid: newCommitOid!, - }); - const mergeParents = newCommit.commit.parent; - const amendedNewCommitOid = await git.commit({ + if (acceptedConflicts.length === 0) { + const mergeCommitOid = await git.commit({ fs, dir: gitDDB.workingDir, author: gitDDB.author, committer: gitDDB.committer, + parent: [oldCommitOid, oldRemoteCommitOid], message: 'merge', - parent: mergeParents, + tree: mergedTreeOid, }); let localCommits: NormalizedCommit[] | undefined; // Get list of commits which has been added to local - if (sync.options.includeCommits) { - const amendedNewCommit = await git.readCommit({ - fs, - dir: gitDDB.workingDir, - oid: amendedNewCommitOid, - }); - - const [baseCommitOid] = await git.findMergeBase({ + if (syncOptions.includeCommits) { + const mergeCommit = await git.readCommit({ fs, dir: gitDDB.workingDir, - oids: [oldCommitOid, oldRemoteCommitOid], + oid: mergeCommitOid!, }); const commitsFromRemote = await getCommitLogs( @@ -271,14 +218,14 @@ export async function syncWorker ( baseCommitOid ); // Add merge commit - localCommits = [...commitsFromRemote, normalizeCommit(amendedNewCommit)]; + localCommits = [...commitsFromRemote, normalizeCommit(mergeCommit)]; } // Need push because it is merged normally. - const syncResultPush = await pushWorker(gitDDB, sync, taskMetadata, true).catch( + const syncResultPush = (await pushWorker(gitDDB, sync, taskMetadata, true, true).catch( (err: Error) => { return err; } - ); + )) as SyncResultPush; if (syncResultPush instanceof Error) { const syncResultMergeAndPushError: SyncResultMergeAndPushError = { @@ -300,7 +247,8 @@ export async function syncWorker ( action: 'merge and push', changes: { local: localChanges, - remote: syncResultPush.changes.remote, + // remote: syncResultPush.changes.remote, + remote: remoteChanges, }, }; if (localCommits) { @@ -318,64 +266,6 @@ export async function syncWorker ( * https://git-scm.com/docs/git-merge#_true_merge */ - const allFileObj: { [key: string]: boolean } = {}; - conflictedIndex.entries().forEach((entry: nodegit.IndexEntry) => { - const stage = nodegit.Index.entryStage(entry); - gitDDB.logger.debug( - CONSOLE_STYLE.bgWhite().fgBlack().tag()`sync_worker: ${stage} : ${entry.path}` - ); - - // entries() returns all files in stage 0, 1, 2 and 3. - // A file may exist in multiple stages. - // Add once per file to allFileObj. - allFileObj[entry.path] = true; - }); - - /** - * NOTE: - * Index from Repository.mergeBranch, Merge.merge or Merge.commit is in-memory only. - * It cannot be used for commit operations. - * Create a new copy of index for commit. - * Repository#refreshIndex() grabs copy of latest index - * See https://github.com/nodegit/nodegit/blob/master/examples/merge-with-conflicts.js - */ - const resolvedIndex = await repos.refreshIndex(); - - const acceptedConflicts: AcceptedConflict[] = []; - - // Try to check conflict for all files in conflicted index. - // console.log('3-way merge..'); - const [mergeBaseCommitOid] = await git.findMergeBase({ - fs, - dir: gitDDB.workingDir, - oids: [oldCommitOid, oldRemoteCommitOid], - }); - - const resolvers: Promise[] = []; - const strategy = sync.options.conflictResolutionStrategy; - // eslint-disable-next-line complexity - Object.keys(allFileObj).forEach(path => { - resolvers.push( - threeWayMerge( - gitDDB, - sync, - strategy!, - resolvedIndex, - path, - mergeBaseCommitOid, - oldCommitOid, - oldRemoteCommitOid, - acceptedConflicts - ).catch(err => { - throw new Err.ThreeWayMergeError(err.message); - }) - ); - }); - await Promise.all(resolvers); - resolvedIndex.conflictCleanup(); - await resolvedIndex.write(); - await resolvedIndex.writeTree(); - acceptedConflicts.sort((a, b) => { return a.fatDoc.name === b.fatDoc.name ? 0 : a.fatDoc.name > b.fatDoc.name ? 1 : -1; }); @@ -392,61 +282,41 @@ export async function syncWorker ( commitMessage = commitMessage.slice(0, -2); } - const overwriteCommitOid = await git.commit({ + const mergeCommitOid = await git.commit({ fs, dir: gitDDB.workingDir, author: gitDDB.author, committer: gitDDB.committer, - parent: [ - await git.resolveRef({ - fs, - dir: gitDDB.workingDir, - ref: 'HEAD', - }), - await git.resolveRef({ - fs, - dir: gitDDB.workingDir, - ref: 'refs/remotes/origin/main', - }), - ], + parent: [oldCommitOid, oldRemoteCommitOid], message: commitMessage, + tree: mergedTreeOid, }); - repos.stateCleanup(); - - const localChanges = await getChanges( - gitDDB.workingDir, - oldCommitOid, - overwriteCommitOid - ); + // const localChanges = await getChanges(gitDDB.workingDir, oldCommitOid, mergeCommitOid); // Get list of commits which has been added to local let localCommits: NormalizedCommit[] | undefined; - if (sync.options.includeCommits) { + if (syncOptions.includeCommits) { const commitsFromRemote = await getCommitLogs( gitDDB.workingDir, oldRemoteCommitOid, - mergeBaseCommitOid + baseCommitOid ); const overwriteCommit = await git.readCommit({ fs, dir: gitDDB.workingDir, - oid: overwriteCommitOid, + oid: mergeCommitOid, }); // Add merge commit localCommits = [...commitsFromRemote, normalizeCommit(overwriteCommit)]; } - const opt = new nodegit.CheckoutOptions(); - opt.checkoutStrategy = nodegit.Checkout.STRATEGY.FORCE; - await nodegit.Checkout.head(repos, opt); - // Push - const syncResultPush = await pushWorker(gitDDB, sync, taskMetadata, true).catch( + const syncResultPush = (await pushWorker(gitDDB, sync, taskMetadata, true, true).catch( (err: Error) => { return err; } - ); + )) as SyncResultPush; if (syncResultPush instanceof Error) { const syncResultResolveConflictsAndPushError: SyncResultResolveConflictsAndPushError = { @@ -470,7 +340,8 @@ export async function syncWorker ( conflicts: acceptedConflicts, changes: { local: localChanges, - remote: syncResultPush.changes.remote, + // remote: syncResultPush.changes.remote, + remote: remoteChanges, }, }; if (localCommits) { @@ -479,6 +350,5 @@ export async function syncWorker ( remote: syncResultPush.commits!.remote, }; } - return syncResultResolveConflictsAndPush; } diff --git a/src/remote/worker_utils.ts b/src/remote/worker_utils.ts index 240f98ac..e32695ee 100644 --- a/src/remote/worker_utils.ts +++ b/src/remote/worker_utils.ts @@ -7,10 +7,10 @@ */ import nodePath from 'path'; +import { serialize } from 'v8'; import git, { ReadBlobResult, ReadCommitResult } from 'isomorphic-git'; import fs from 'fs-extra'; -import { normalizeCommit } from '../utils'; -import { GIT_DOCUMENTDB_METADATA_DIR, JSON_EXT } from '../const'; +import { normalizeCommit, utf8decode } from '../utils'; import { Err } from '../error'; import { ChangedFile, @@ -21,9 +21,9 @@ import { FatTextDoc, JsonDoc, NormalizedCommit, + SerializeFormat, } from '../types'; -import { GitDDBInterface } from '../types_gitddb'; -import { blobToBinary, blobToJsonDoc, blobToText } from '../crud/blob'; +import { blobToBinary, blobToJsonDoc, blobToText, textToJsonDoc } from '../crud/blob'; /** * Write blob to file system @@ -31,11 +31,11 @@ import { blobToBinary, blobToJsonDoc, blobToText } from '../crud/blob'; * @throws {@link Err.CannotCreateDirectoryError} */ export async function writeBlobToFile ( - gitDDB: GitDDBInterface, + workingDir: string, name: string, - data: string + data: string | Uint8Array ) { - const filePath = nodePath.resolve(gitDDB.workingDir, name); + const filePath = nodePath.resolve(workingDir, name); const dir = nodePath.dirname(filePath); await fs.ensureDir(dir).catch((err: Error) => { return Promise.reject(new Err.CannotCreateDirectoryError(err.message)); @@ -43,23 +43,31 @@ export async function writeBlobToFile ( await fs.writeFile(filePath, data); } -export /** +/** + * getFatDocFromData + * * @throws {@link Err.InvalidJsonObjectError} */ -async function getFatDocFromData ( +export async function getFatDocFromData ( data: string | Uint8Array, fullDocPath: string, - docType: DocType + docType: DocType, + serializeFormat: SerializeFormat ) { let fatDoc: FatDoc; const { oid } = await git.hashBlob({ object: data }); if (docType === 'json') { - const _id = fullDocPath.replace(new RegExp(JSON_EXT + '$'), ''); + const _id = serializeFormat.removeExtension(fullDocPath); if (typeof data !== 'string') { - throw new Err.InvalidJsonObjectError(_id); + data = utf8decode(data); } try { - const jsonDoc = (JSON.parse(data) as unknown) as JsonDoc; + const [, extension] = fullDocPath.match(/.+(\..+?)$/)!; + const jsonDoc = (textToJsonDoc( + data, + serializeFormat, + extension + ) as unknown) as JsonDoc; if (jsonDoc._id !== undefined) { // Overwrite _id property by _id if JsonDoc is created by GitDocumentedDB (_id !== undefined). jsonDoc._id = _id; @@ -76,6 +84,9 @@ async function getFatDocFromData ( } } else if (docType === 'text') { + if (typeof data !== 'string') { + data = utf8decode(data); + } fatDoc = { name: fullDocPath, fileOid: oid, @@ -94,32 +105,48 @@ async function getFatDocFromData ( return fatDoc!; } +/** + * getFatDocFromOid + * + * @throws {@link Err.InvalidJsonObjectError} (from getFatDocFromReadBlobResult) + */ export async function getFatDocFromOid ( workingDir: string, fullDocPath: string, fileOid: string, - docType: DocType + docType: DocType, + serializeFormat: SerializeFormat ) { const readBlobResult = await git.readBlob({ fs, dir: workingDir, oid: fileOid, }); - return getFatDocFromReadBlobResult(fullDocPath, readBlobResult, docType); + return getFatDocFromReadBlobResult(fullDocPath, readBlobResult, docType, serializeFormat); } /** + * getFatDocFromReadBlobResult + * * @throws {@link Err.InvalidJsonObjectError} */ export function getFatDocFromReadBlobResult ( fullDocPath: string, readBlobResult: ReadBlobResult, - docType: DocType + docType: DocType, + serializeFormat: SerializeFormat ) { let fatDoc: FatDoc; if (docType === 'json') { - const _id = fullDocPath.replace(new RegExp(JSON_EXT + '$'), ''); - fatDoc = blobToJsonDoc(_id, readBlobResult, true) as FatJsonDoc; + const _id = serializeFormat.removeExtension(fullDocPath); + const [, extension] = fullDocPath.match(/.+(\..+?)$/)!; + fatDoc = blobToJsonDoc( + _id, + readBlobResult, + true, + serializeFormat, + extension + ) as FatJsonDoc; } else if (docType === 'text') { fatDoc = blobToText(fullDocPath, readBlobResult, true) as FatTextDoc; @@ -133,14 +160,15 @@ export function getFatDocFromReadBlobResult ( /** * Get changed files * - * @throws {@link Err.InvalidJsonObjectError} (from getDocument()) + * @throws {@link Err.InvalidJsonObjectError} (from getFatDocFromOid) * * @internal */ export async function getChanges ( workingDir: string, - oldCommitOid: string, - newCommitOid: string + oldCommitOid: string | undefined, + newCommitOid: string, + serializeFormat: SerializeFormat ) { return await git.walk({ fs, @@ -153,11 +181,109 @@ export async function getChanges ( if (fullDocPath === '.') { return; } - if (fullDocPath.startsWith(GIT_DOCUMENTDB_METADATA_DIR)) { + if (oldCommitOid === undefined) { + // Must set null explicitly. + a = null; + } + + const docType: DocType = serializeFormat.hasObjectExtension(fullDocPath) + ? 'json' + : 'text'; + if (docType === 'text') { + // TODO: select binary or text by .gitattribtues + } + + const aType = a === null ? undefined : await a.type(); + const bType = b === null ? undefined : await b.type(); + + if (aType === 'tree' || bType === 'tree') { + return; + } + // generate ids + const aOid = a === null ? undefined : await a.oid(); + const bOid = b === null ? undefined : await b.oid(); + + let change: ChangedFile; + if (bOid === undefined && aOid !== undefined) { + change = { + operation: 'delete', + old: await getFatDocFromOid( + workingDir, + fullDocPath, + aOid, + docType, + serializeFormat + ), + }; + } + else if (aOid === undefined && bOid !== undefined) { + change = { + operation: 'insert', + new: await getFatDocFromOid( + workingDir, + fullDocPath, + bOid, + docType, + serializeFormat + ), + }; + } + else if (aOid !== undefined && bOid !== undefined && aOid !== bOid) { + change = { + operation: 'update', + old: await getFatDocFromOid( + workingDir, + fullDocPath, + aOid, + docType, + serializeFormat + ), + new: await getFatDocFromOid( + workingDir, + fullDocPath, + bOid, + docType, + serializeFormat + ), + }; + } + else { + return; + } + return change; + }, + }); +} + +/** + * Get and write changed files on local + * + * @throws {@link Err.InvalidJsonObjectError} (from getFatDocFromOid) + * @throws {@link Err.CannotCreateDirectoryError} (from writeBlobToFile) + * + * @internal + */ +export async function getAndWriteLocalChanges ( + workingDir: string, + oldCommitOid: string, + newCommitOid: string, + serializeFormat: SerializeFormat +) { + return await git.walk({ + fs, + dir: workingDir, + trees: [git.TREE({ ref: oldCommitOid }), git.TREE({ ref: newCommitOid })], + // @ts-ignore + // eslint-disable-next-line complexity + map: async function (fullDocPath, [a, b]) { + // ignore directories + if (fullDocPath === '.') { return; } - const docType: DocType = fullDocPath.endsWith('.json') ? 'json' : 'text'; + const docType: DocType = serializeFormat.hasObjectExtension(fullDocPath) + ? 'json' + : 'text'; if (docType === 'text') { // TODO: select binary or text by .gitattribtues } @@ -176,21 +302,72 @@ export async function getChanges ( if (bOid === undefined && aOid !== undefined) { change = { operation: 'delete', - old: await getFatDocFromOid(workingDir, fullDocPath, aOid, docType), + old: await getFatDocFromOid( + workingDir, + fullDocPath, + aOid, + docType, + serializeFormat + ), }; + await git.remove({ fs, dir: workingDir, filepath: fullDocPath }); + const path = nodePath.resolve(workingDir, fullDocPath); + await fs.remove(path).catch(() => { + throw new Err.CannotDeleteDataError(); + }); } else if (aOid === undefined && bOid !== undefined) { change = { operation: 'insert', - new: await getFatDocFromOid(workingDir, fullDocPath, bOid, docType), + new: await getFatDocFromOid( + workingDir, + fullDocPath, + bOid, + docType, + serializeFormat + ), }; + if (change.new.type === 'json') { + await writeBlobToFile( + workingDir, + fullDocPath, + serializeFormat.serialize(change.new.doc).data + ); + } + else if (change.new.type === 'text' || change.new.type === 'binary') { + await writeBlobToFile(workingDir, fullDocPath, change.new.doc); + } + await git.add({ fs, dir: workingDir, filepath: fullDocPath }); } else if (aOid !== undefined && bOid !== undefined && aOid !== bOid) { change = { operation: 'update', - old: await getFatDocFromOid(workingDir, fullDocPath, aOid, docType), - new: await getFatDocFromOid(workingDir, fullDocPath, bOid, docType), + old: await getFatDocFromOid( + workingDir, + fullDocPath, + aOid, + docType, + serializeFormat + ), + new: await getFatDocFromOid( + workingDir, + fullDocPath, + bOid, + docType, + serializeFormat + ), }; + if (change.new.type === 'json') { + await writeBlobToFile( + workingDir, + fullDocPath, + serializeFormat.serialize(change.new.doc).data + ); + } + else if (change.new.type === 'text' || change.new.type === 'binary') { + await writeBlobToFile(workingDir, fullDocPath, change.new.doc); + } + await git.add({ fs, dir: workingDir, filepath: fullDocPath }); } else { return; @@ -218,7 +395,7 @@ export async function getChanges ( export async function getCommitLogs ( workingDir: string, walkFromCommitOid: string, - walkToCommitOid: string, + walkToCommitOid?: string, walkToCommitOid2?: string ): Promise { // Return partial logs. @@ -250,16 +427,17 @@ export async function getCommitLogs ( /** * Calc distance */ -export async function calcDistance ( - workingDir: string, +export function calcDistance ( + baseCommitOid: string, localCommitOid: string, remoteCommitOid: string ) { - const [baseCommitOid] = await git.findMergeBase({ - fs, - dir: workingDir, - oids: [localCommitOid, remoteCommitOid], - }); + if (baseCommitOid === undefined) { + return { + ahead: undefined, + behind: undefined, + }; + } return { ahead: localCommitOid !== baseCommitOid ? 1 : 0, behind: remoteCommitOid !== baseCommitOid ? 1 : 0, diff --git a/src/serialize_format.ts b/src/serialize_format.ts new file mode 100644 index 00000000..88b6a89a --- /dev/null +++ b/src/serialize_format.ts @@ -0,0 +1,61 @@ +import { FRONT_MATTER_POSTFIX, JSON_POSTFIX, YAML_POSTFIX } from './const'; +import { JsonDoc, SerializeFormat, SerializeFormatLabel } from './types'; +import { toFrontMatterMarkdown, toSortedJSONString, toYAML } from './utils'; + +export class SerializeFormatJSON implements SerializeFormat { + format: SerializeFormatLabel = 'json'; + firstExtension = JSON_POSTFIX; + secondExtension = undefined; + + extension () { + return JSON_POSTFIX; + } + + removeExtension (path: string) { + if (path.endsWith(this.firstExtension)) + return path.replace(new RegExp(this.firstExtension + '$'), ''); + return path; + } + + hasObjectExtension (path: string) { + if (path.endsWith(this.firstExtension)) return true; + return false; + } + + serialize (doc: JsonDoc) { + return { extension: JSON_POSTFIX, data: toSortedJSONString(doc) }; + } +} + +export class SerializeFormatFrontMatter implements SerializeFormat { + format: SerializeFormatLabel = 'front-matter'; + firstExtension = FRONT_MATTER_POSTFIX; + secondExtension = YAML_POSTFIX; + + extension (doc?: JsonDoc) { + if (doc !== undefined && doc._body === undefined) return YAML_POSTFIX; + return FRONT_MATTER_POSTFIX; + } + + removeExtension (path: string) { + if (path.endsWith(this.firstExtension)) + return path.replace(new RegExp(this.firstExtension + '$'), ''); + if (path.endsWith(this.secondExtension)) + return path.replace(new RegExp(this.secondExtension + '$'), ''); + return path; + } + + hasObjectExtension (path: string) { + if (path.endsWith(this.firstExtension) || path.endsWith(this.secondExtension)) + return true; + return false; + } + + serialize (doc: JsonDoc) { + const extension = this.extension(doc); + return { + extension, + data: extension === YAML_POSTFIX ? toYAML(doc) : toFrontMatterMarkdown(doc), + }; + } +} diff --git a/src/task_queue.ts b/src/task_queue.ts index 0d80e5e0..93520990 100644 --- a/src/task_queue.ts +++ b/src/task_queue.ts @@ -6,10 +6,14 @@ * found in the LICENSE file in the root directory of this source tree. */ -import { monotonicFactory } from 'ulid'; -import { Logger } from 'tslog'; +/** + * ! Must import both clearInterval and setInterval from 'timers' + */ +import { clearInterval, setInterval } from 'timers'; + +import { decodeTime, monotonicFactory } from 'ulid'; import AsyncLock from 'async-lock'; -import { Task, TaskMetadata, TaskStatistics } from './types'; +import { ColoredLogger, Task, TaskMetadata, TaskStatistics } from './types'; import { CONSOLE_STYLE, sleep } from './utils'; import { Err } from './error'; @@ -21,11 +25,10 @@ import { Err } from './error'; export class TaskQueue { // Monotonic counter private _ulid = monotonicFactory(); - private _lock = new AsyncLock(); + private _lock: AsyncLock | undefined = new AsyncLock(); - private _logger: Logger; + private _logger: ColoredLogger; - // @ts-ignore private _taskQueue: Task[] = []; private _isTaskQueueWorking = false; @@ -46,12 +49,18 @@ export class TaskQueue { private _currentTask: Task | undefined = undefined; + private _checkTimer: NodeJS.Timeout | undefined; + private _checkTimerInterval = 100; + /** * Constructor * + * @remarks + * Must call start() after new TaskQueue() + * * @public */ - constructor (logger: Logger) { + constructor (logger: ColoredLogger) { this._logger = logger; } @@ -60,7 +69,7 @@ export class TaskQueue { * * @internal */ - setLogger (logger: Logger) { + setLogger (logger: ColoredLogger) { this._logger = logger; } @@ -103,15 +112,20 @@ export class TaskQueue { // eslint-disable-next-line complexity pushToTaskQueue (task: Task) { // Critical section - this._lock - // eslint-disable-next-line complexity - .acquire('taskQueue', () => { + this._lock! // eslint-disable-next-line complexity + .acquire('TaskQueue', () => { // Skip consecutive sync/push events + this._logger.silly( + `Try to push ${task.label}@${task.taskId} into ${JSON.stringify(this._taskQueue)}` + ); if ( (this._taskQueue.length === 0 && + this._currentTask?.syncRemoteName === task.syncRemoteName && ((this._currentTask?.label === 'sync' && task.label === 'sync') || (this._currentTask?.label === 'push' && task.label === 'push'))) || (this._taskQueue.length > 0 && + this._taskQueue[this._taskQueue.length - 1].syncRemoteName === + task.syncRemoteName && ((this._taskQueue[this._taskQueue.length - 1].label === 'sync' && task.label === 'sync') || (this._taskQueue[this._taskQueue.length - 1].label === 'push' && @@ -133,25 +147,26 @@ export class TaskQueue { shortName: task.shortName, collectionPath: task.collectionPath, enqueueTime: task.enqueueTime, + syncRemoteName: task.syncRemoteName, + debounceTime: task.debounceTime, }; + if (task.enqueueCallback) { try { task.enqueueCallback(taskMetadata); } catch (e) { this._logger.debug( - CONSOLE_STYLE.bgGreen() - .fgRed() - .tag()`Error in enqueueCallback (fullDocPath: ${ + `Error in enqueueCallback (fullDocPath: ${ task.collectionPath! + task.shortName - }) ${e}` + }) ${e}`, + CONSOLE_STYLE.bgGreen().fgRed().tag ); } } - this._execTaskQueue(); }) .catch(e => { if (e instanceof Err.ConsecutiveSyncSkippedError) { - this._logger.debug(CONSOLE_STYLE.bgGreen().fgRed().tag()`${e.message}`); + this._logger.debug(e.message, CONSOLE_STYLE.bgGreen().fgRed().tag); } else { throw e; @@ -160,14 +175,40 @@ export class TaskQueue { } /** - * Clear TaskQueue + * Start TaskQueue + * + * @public + */ + start () { + if (this._lock === undefined) { + this._lock = new AsyncLock(); + } + + if (this._checkTimer === undefined) { + this._checkTimer = setInterval(() => { + this._checkTaskQueue(); + }, this._checkTimerInterval); + } + } + + /** + * Stop TaskQueue * * @public */ - clear () { - // Clear not queued jobs - // @ts-ignore - this._lock.queues.taskQueue = null; + stop () { + // Clear not queued job + + if (this._checkTimer !== undefined) { + clearInterval(this._checkTimer); + this._checkTimer = undefined; + } + + if (this._lock !== undefined) { + // @ts-ignore + this._lock.queues.taskQueue = null; + } + this._lock = undefined; // Cancel queued tasks this._taskQueue.forEach(task => task.cancel()); @@ -219,54 +260,155 @@ export class TaskQueue { return isTimeout; } + private _pullTargetTask (targetIndex: number) { + if (targetIndex >= this._taskQueue.length) { + return undefined; + } + if (targetIndex === 0) { + return this._taskQueue.shift(); + } + const [task] = this._taskQueue.splice(targetIndex, 1); + return task; + } + /** + * checkTaskQueue * @internal */ - private _execTaskQueue () { - if (this._taskQueue.length > 0 && !this._isTaskQueueWorking) { - this._currentTask = this._taskQueue.shift(); - if (this._currentTask !== undefined && this._currentTask.func !== undefined) { - const label = this._currentTask.label; - const shortId = this._currentTask.shortId; - const shortName = this._currentTask.shortName; - const collectionPath = this._currentTask.collectionPath; - const fullDocPath = collectionPath ? collectionPath + shortName : ''; - const taskId = this._currentTask.taskId; - - this._isTaskQueueWorking = true; - this._logger.debug( - CONSOLE_STYLE.bgYellow().fgBlack().tag()`Start: ${label}(${fullDocPath})` - ); + private _checkTaskQueue () { + if (this._lock === undefined) return; + if (this._lock.isBusy()) return; - const beforeResolve = () => { - this._logger.debug( - CONSOLE_STYLE.bgGreen().fgBlack().tag()`End: ${label}(${fullDocPath})` - ); - this._statistics[label]++; - this._isTaskQueueWorking = false; - this._currentTask = undefined; - }; - const beforeReject = () => { - this._logger.debug( - CONSOLE_STYLE.bgGreen().fgRed().tag()`End with error: ${label}(${fullDocPath})` - ); - this._statistics[label]++; - this._isTaskQueueWorking = false; - this._currentTask = undefined; - }; - const taskMetadata: TaskMetadata = { - label, - taskId, - shortId, - shortName, - collectionPath, - enqueueTime: this._currentTask.enqueueTime, - }; + // eslint-disable-next-line complexity + this._lock!.acquire('TaskQueue', () => { + if (this._taskQueue.length === 0 || this._isTaskQueueWorking) return; - this._currentTask.func(beforeResolve, beforeReject, taskMetadata).finally(() => { - this._execTaskQueue(); - }); + let taskIndex = 0; + while (taskIndex < this._taskQueue.length) { + const targetTask = this._taskQueue[taskIndex]; + + if (targetTask.debounceTime === undefined || targetTask.debounceTime! < 0) { + this._currentTask = this._pullTargetTask(taskIndex); + if (this._currentTask !== undefined) this._execTask(); + return; + } + + if (targetTask.label !== 'put' && targetTask.label !== 'update') { + this._currentTask = this._pullTargetTask(taskIndex); + if (this._currentTask !== undefined) this._execTask(); + return; + } + const targetFullDocPath = targetTask.collectionPath! + targetTask.shortName!; + const expiredTime = decodeTime(targetTask.enqueueTime!) + targetTask.debounceTime!; + const current = Date.now(); + + let nextPutUpdateExist = false; + let nextDeleteExist = false; + let nextInsertExist = false; + for (let i = taskIndex + 1; i < this._taskQueue.length; i++) { + const tmpTask = this._taskQueue[i]; + if (decodeTime(tmpTask.enqueueTime!) > expiredTime) break; + + if ( + (tmpTask.label === 'put' || + tmpTask.label === 'insert' || + tmpTask.label === 'update' || + tmpTask.label === 'delete') && + targetFullDocPath === tmpTask.collectionPath! + tmpTask.shortName! + ) { + // eslint-disable-next-line max-depth + if (tmpTask.label === 'delete') { + nextDeleteExist = true; + break; + } + if (tmpTask.label === 'insert') { + nextInsertExist = true; + break; + } + nextPutUpdateExist = true; + break; + } + } + + if (nextPutUpdateExist) { + const cancelTask = this._pullTargetTask(taskIndex); + cancelTask?.cancel(); + continue; + } + else if (nextDeleteExist) { + this._currentTask = this._pullTargetTask(taskIndex); + if (this._currentTask !== undefined) this._execTask(); + return; + } + else if (nextInsertExist) { + this._currentTask = this._pullTargetTask(taskIndex); + if (this._currentTask !== undefined) this._execTask(); + return; + } + + if (expiredTime <= current) { + this._currentTask = this._pullTargetTask(taskIndex); + if (this._currentTask !== undefined) this._execTask(); + return; + } + taskIndex++; } + }); + } + + /** + * execTask + * @internal + */ + // eslint-disable-next-line complexity + private _execTask () { + if (this._currentTask !== undefined && this._currentTask.func !== undefined) { + this._isTaskQueueWorking = true; + + const label = this._currentTask.label; + const shortId = this._currentTask.shortId; + const shortName = this._currentTask.shortName; + const collectionPath = this._currentTask.collectionPath; + const fullDocPath = collectionPath ? collectionPath + shortName : ''; + const taskId = this._currentTask.taskId; + const syncRemoteName = this._currentTask.syncRemoteName; + + this._logger.debug( + `Start: ${label}(${fullDocPath})@${taskId}`, + CONSOLE_STYLE.bgYellow().fgBlack().tag + ); + + const beforeResolve = () => { + this._logger.debug( + `End: ${label}(${fullDocPath})@${taskId}`, + CONSOLE_STYLE.bgGreen().fgBlack().tag + ); + this._statistics[label]++; + }; + const beforeReject = () => { + this._logger.debug( + `End with error: ${label}(${fullDocPath})@${taskId}`, + CONSOLE_STYLE.bgGreen().fgRed().tag + ); + this._statistics[label]++; + }; + const taskMetadata: TaskMetadata = { + label, + taskId, + shortId, + shortName, + collectionPath, + enqueueTime: this._currentTask.enqueueTime, + syncRemoteName, + }; + + this._currentTask.func(beforeResolve, beforeReject, taskMetadata).finally(() => { + this._logger.silly( + `Clear currentTask: ${this._currentTask?.label}@${this._currentTask?.taskId}` + ); + this._isTaskQueueWorking = false; + this._currentTask = undefined; + }); } } } diff --git a/src/types.ts b/src/types.ts index e938fdc6..2b2d0269 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,7 +6,14 @@ * found in the LICENSE file in the root directory of this source tree. */ -import { TLogLevelName } from 'tslog'; +import { ILogObject, TLogLevelName } from 'tslog'; + +/** + * Plugin types + * + * @public + */ +export type PluginTypes = 'db' | 'remote'; /** * Database Options @@ -38,6 +45,14 @@ import { TLogLevelName } from 'tslog'; * * logLevel - Default is 'info'. * + * schema - Schema for a specific document type. + * + * serializeFormat - Format for serialization + * + * logToTransport - logToTransport function for all log levels. See https://tslog.js.org/#/?id=transports + * + * logColorEnabled - Enable color for console log. Default is true. When you write log into a file by logToTransport, false is recommended. + * * @public */ export type DatabaseOptions = { @@ -45,6 +60,9 @@ export type DatabaseOptions = { dbName: string; logLevel?: TLogLevelName; schema?: Schema; + serialize?: SerializeFormatLabel; + logToTransport?: (logObject: ILogObject) => void; + logColorEnabled?: boolean; }; /** @@ -65,18 +83,22 @@ export type OpenOptions = { * @public */ export type Schema = { - json: JsonDiffOptions; + json: JsonDiffPatchOptions; }; /** - * JsonDiffOptions + * JsonDiffPatchOptions * * @remarks - * - plainTextProperties: Only property whose key matches plainTextProperties uses text diff and patch algorithm (google-diff-match-patch). + * - plainTextProperties: Only property whose key matches plainTextProperties uses text-diff-and-patch algorithm (google-diff-match-patch). + * + * - keyInArrayedObject: To diff between arrays that contain objects as elements, you must specify a key in the object. See https://github.com/benjamine/jsondiffpatch/blob/master/docs/arrays.md#an-object-hash + * + * - keyOfUniqueArray: Set a key of a unique array. Unique array never include duplicated members after JSON patch. * * @example * ``` - * e.g. + * Example of plainTextProperties: * { a: { b: true }, c: true } matches 'b' (whose ancestor is only 'a') and 'c'. * { a: { _all: true } } matches all child properties of 'a'. * { a: { _regex: /abc/ } } matches child properties of 'a' which match /abc/. @@ -84,8 +106,9 @@ export type Schema = { * * @public */ -export type JsonDiffOptions = { - idOfSubtree?: string[]; +export type JsonDiffPatchOptions = { + keyInArrayedObject?: string[]; + keyOfUniqueArray?: string[]; plainTextProperties?: { [key: string]: any }; }; @@ -121,12 +144,15 @@ export type DatabaseOpenResult = DatabaseInfo & { * * - version: A version of the GitDocumentDB specification. The version can be used for database migration. * + * - serialize: Serialize format of the database. + * * @public */ export type DatabaseInfo = { dbId: string; creator: string; version: string; + serialize: SerializeFormatLabel; }; /** @@ -188,9 +214,9 @@ export type Doc = JsonDoc | string | Uint8Array; * Metadata for JsonDoc * * @remarks - * - _id: _id of a JSON document. This is a file name without .json extension. + * - _id: _id of a JSON document. This is a file name without extension. * - * - name: A file name in Git. e.g.) "foo.json", "bar/baz.json" + * - name: A file name in Git. e.g.) "foo.json", "bar/baz.md" * * - fileOid: SHA-1 hash of Git object (40 characters) * @@ -282,6 +308,28 @@ export type FatBinaryDoc = BinaryDocMetadata & { */ export type FatDoc = FatJsonDoc | FatTextDoc | FatBinaryDoc; +/** + * Format for serialization + * + * @public + */ +export type SerializeFormatLabel = 'json' | 'front-matter'; + +/** + * Interface for serialize format classes + * + * @internal + */ +export interface SerializeFormat { + format: SerializeFormatLabel; + firstExtension: string; + secondExtension: string | undefined; + removeExtension: (path: string) => string; + extension: (doc?: JsonDoc) => string; + hasObjectExtension: (path: string) => boolean; + serialize: (doc: JsonDoc) => { extension: string; data: string }; +} + /** * CollectionPath * @@ -309,10 +357,17 @@ export type CollectionPath = string; /** * Options for Collection constructor * + * @remarks + * - namePrefix: Automatically generated _id has a specified prefix in the collection. + * + * - debounceTime: put/insert/update operations for the same document are debounced by specified milliseconds in the collection. Default is -1 (do not debounce). + * * @public */ export type CollectionOptions = { namePrefix?: string; + debounceTime?: number; + idGenerator?: () => string; }; /** @@ -327,6 +382,8 @@ export type CollectionOptions = { * * - enqueueCallback: A callback function called just after this put task is enqueued to TaskQueue. * + * - debounceTime: put/insert/update operations for the same document are debounced by specified milliseconds. This overwrite the same option in Collection Class. Default is -1 (do not debounce). + * * @public */ export type PutOptions = { @@ -334,6 +391,7 @@ export type PutOptions = { insertOrUpdate?: 'insert' | 'update'; taskId?: string; enqueueCallback?: (taskMetadata: TaskMetadata) => void; + debounceTime?: number; }; /** @@ -435,7 +493,7 @@ export type FindOptions = { * Result of put APIs (put, update, insert, putFatDoc, updateFatDoc, and insertFatDoc) * * @remarks - * - _id: _id of a JSON document. This is a file name without .json extension. PutResult does not have _id if a document is not {@link JsonDoc} type. + * - _id: _id of a JSON document. This is a file name without extension. PutResult does not have _id if a document is not {@link JsonDoc} type. * * - name: A file name in Git. e.g.) "foo.json", "bar/baz.md" * @@ -482,7 +540,7 @@ export type PutResultBinary = { * Result of delete() * * @remarks - * - _id: _id of a JSON document. This is a file name without .json extension. PutResult does not have _id if a document is not {@link JsonDoc} type. + * - _id: _id of a JSON document. This is a file name without extension. PutResult does not have _id if a document is not {@link JsonDoc} type. * * - name: A file name in Git. e.g.) "foo.json", "bar/baz.md" * @@ -567,6 +625,7 @@ export type SyncDirection = 'pull' | 'push' | 'both'; */ export type ConnectionSettingsGitHub = { type: 'github'; + engine?: string; personalAccessToken?: string; private?: boolean; }; @@ -578,6 +637,7 @@ export type ConnectionSettingsGitHub = { */ export type ConnectionSettingsSSH = { type: 'ssh'; + engine?: string; privateKeyPath: string; publicKeyPath: string; passPhrase?: string; @@ -590,6 +650,7 @@ export type ConnectionSettingsSSH = { */ export type ConnectionSettingsNone = { type: 'none'; + engine?: string; }; /** @@ -781,6 +842,8 @@ export type TaskMetadata = { shortName?: string; collectionPath?: string; enqueueTime?: string; + syncRemoteName?: string; + debounceTime?: number; }; /** @@ -1168,3 +1231,28 @@ export interface IJsonPatch { strategy?: ConflictResolutionStrategyLabels ): JsonDoc; } + +/** + * Colored log + * + * @internal + */ +export type ColoredLog = ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string +) => void; + +/** + * Colored logger + * + * @internal + */ +export type ColoredLogger = { + silly: ColoredLog; + debug: ColoredLog; + trace: ColoredLog; + info: ColoredLog; + warn: ColoredLog; + error: ColoredLog; + fatal: ColoredLog; +}; diff --git a/src/types_collection.ts b/src/types_collection.ts index f41a76a0..f705d167 100644 --- a/src/types_collection.ts +++ b/src/types_collection.ts @@ -28,7 +28,7 @@ export type ICollection = CollectionInterface & /*********************************************** * Public methods ***********************************************/ - generateId(): string; + generateId(seedTime?: number): string; }; /** diff --git a/src/types_gitddb.ts b/src/types_gitddb.ts index 443da0f7..9058c154 100644 --- a/src/types_gitddb.ts +++ b/src/types_gitddb.ts @@ -6,16 +6,18 @@ * found in the LICENSE file in the root directory of this source tree. */ -import nodegit from '@sosuisen/nodegit'; import { Logger, TLogLevelName } from 'tslog'; +import { SerializeFormatFrontMatter, SerializeFormatJSON } from './serialize_format'; import { TaskQueue } from './task_queue'; import { + ColoredLogger, DatabaseCloseOption, DatabaseOpenResult, NormalizedCommit, OpenOptions, RemoteOptions, Schema, + SerializeFormatLabel, SyncResult, } from './types'; import { ICollection } from './types_collection'; @@ -31,13 +33,15 @@ export interface GitDDBInterface { /*********************************************** * Public properties (readonly) ***********************************************/ + serializeFormat: SerializeFormatJSON | SerializeFormatFrontMatter; defaultBranch: string; localDir: string; dbName: string; isOpened: boolean; workingDir: string; dbId: string; - logger: Logger; + tsLogger: Logger; + logger: ColoredLogger; schema: Schema; taskQueue: TaskQueue; isClosing: boolean; @@ -82,13 +86,5 @@ export interface GitDDBInterface { saveAuthor(): Promise; loadAuthor(): Promise; - saveAppInfo(info: { [key: string]: any }): void; - loadAppInfo(): { [key: string]: any }; - loadDbInfo(): void; - - /* deprecate */ - repository(): nodegit.Repository | undefined; - /* deprecate */ - setRepository(repos: nodegit.Repository): void; } diff --git a/src/types_sync.ts b/src/types_sync.ts index f4e2d9c5..27012dd3 100644 --- a/src/types_sync.ts +++ b/src/types_sync.ts @@ -1,4 +1,3 @@ -import nodegit from '@sosuisen/nodegit'; import { JsonDiff } from './remote/json_diff'; import { RemoteRepository } from './remote/remote_repository'; import { @@ -15,6 +14,7 @@ import { SyncRemoteChangeCallback, SyncResult, SyncResultCancel, + SyncResultNop, SyncResultPush, SyncResumeCallback, SyncStartCallback, @@ -30,13 +30,16 @@ export interface SyncInterface { * Public properties (readonly) ***********************************************/ remoteURL: string; + engine: string; remoteRepository: RemoteRepository; options: RemoteOptions; - upstreamBranch: string; + remoteName: string; /*********************************************** * Public properties ***********************************************/ + runBeforeLiveSync: (() => void) | undefined; + /** * @internal */ @@ -52,29 +55,25 @@ export interface SyncInterface { error: { collectionPath: string; func: SyncErrorCallback }[]; }; - credentialCallbacks: { [key: string]: any }; - jsonDiff: JsonDiff; jsonPatch: IJsonPatch; /*********************************************** * Public methods ***********************************************/ - init(repos: nodegit.Repository): Promise; + init(): Promise; pause(): void; resume(options?: { interval?: number; retry?: number }): void; close(): void; - tryPush(): Promise; + tryPush(): Promise; trySync(): Promise; - enqueuePushTask(): Promise; - enqueueSyncTask(): Promise; currentRetries(): number; on(event: SyncEvent, callback: SyncCallback, collectionPath?: string): SyncInterface; - off(event: SyncEvent, callback: SyncCallback): void; + off(event: SyncEvent, callback: SyncCallback): SyncInterface; } /** diff --git a/src/utils.ts b/src/utils.ts index 2e291a06..f1eedad1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -6,11 +6,26 @@ * found in the LICENSE file in the root directory of this source tree. */ -import path from 'path'; -import nodegit from '@sosuisen/nodegit'; -import { ReadCommitResult } from 'isomorphic-git'; -import { DocMetadata, DocType, NormalizedCommit } from './types'; -import { GIT_DOCUMENTDB_METADATA_DIR, JSON_EXT } from './const'; +import fs from 'fs-extra'; +import yaml from 'js-yaml'; +import { + readBlob, + ReadCommitResult, + readTree, + resolveRef, + TreeEntry, + TreeObject, +} from 'isomorphic-git'; +import { + BinaryDocMetadata, + DocMetadata, + DocType, + JsonDocMetadata, + NormalizedCommit, + SerializeFormat, + TextDocMetadata, +} from './types'; +import { GIT_DOCUMENTDB_METADATA_DIR } from './const'; /** * @internal @@ -23,9 +38,19 @@ export function sleep (msec: number) { const decoder = new TextDecoder(); // default 'utf-8' or 'utf8' // eslint-disable-next-line @typescript-eslint/naming-convention const encoder = new TextEncoder(); // default 'utf-8' or 'utf8' +/** + * utf8decode + * + * @internal + */ export function utf8decode (uint8array: Uint8Array) { return decoder.decode(uint8array); } +/** + * utf8encode + * + * @internal + */ export function utf8encode (utf8: string) { return encoder.encode(utf8); } @@ -59,76 +84,129 @@ export function toSortedJSONString (obj: Record) { ); } +export function toYAML (obj: Record) { + return yaml.dump(obj, { sortKeys: true, lineWidth: -1 }); +} + +export function toFrontMatterMarkdown (obj: Record) { + const body = typeof obj._body === 'string' ? obj._body : ''; + const clone = JSON.parse(JSON.stringify(obj)); + delete clone._body; + let hasOnlyId = true; + for (const key of Object.keys(clone)) { + if (key !== '_id') { + hasOnlyId = false; + break; + } + } + if (hasOnlyId) { + return body; + } + + const frontMatter = + '---\n' + yaml.dump(clone, { sortKeys: true, lineWidth: -1 }) + '---\n'; + return frontMatter + body; +} + /** * Get metadata of all files from current Git index * * @internal */ // eslint-disable-next-line complexity -export async function getAllMetadata (repos: nodegit.Repository) { +export async function getAllMetadata ( + workingDir: string, + serializeFormat: SerializeFormat +): Promise { const files: DocMetadata[] = []; - const head = await nodegit.Reference.nameToId(repos, 'HEAD').catch(e => false); - if (head) { - const headCommit = await repos.getCommit(head as nodegit.Oid); - const localTree = await headCommit.getTree(); - const directories: nodegit.Tree[] = []; - directories.push(localTree); - - while (directories.length > 0) { - const dir = directories.shift(); - if (dir === undefined) break; - const entries = dir.entries(); // returns entry by alphabetical order - while (entries.length > 0) { - const entry = entries.shift(); - if (entry?.isDirectory()) { - // eslint-disable-next-line max-depth - if (entry.name() !== GIT_DOCUMENTDB_METADATA_DIR) { - // eslint-disable-next-line no-await-in-loop - const subtree = await entry.getTree(); - directories.push(subtree); - } + const commitOid = await resolveRef({ fs, dir: workingDir, ref: 'HEAD' }).catch( + () => undefined + ); + + if (commitOid === undefined) return []; + + const treeResult = (await readTree({ + fs, + dir: workingDir, + oid: commitOid, + }).catch(() => undefined))!; + + const directories: { path: string; entries: TreeObject }[] = []; // type TreeObject = Array + const targetDir = ''; + if (treeResult) { + directories.push({ path: targetDir, entries: treeResult.tree }); + } + + const docs: DocMetadata[] = []; + while (directories.length > 0) { + const directory = directories.shift(); + if (directory === undefined) break; + + const entries: TreeEntry[] = directory.entries; + + for (const entry of entries) { + const fullDocPath = + directory.path !== '' ? `${directory.path}/${entry.path}` : entry.path; + if (entry.type === 'tree') { + if (fullDocPath !== GIT_DOCUMENTDB_METADATA_DIR) { + // eslint-disable-next-line no-await-in-loop + const { tree } = await readTree({ + fs, + dir: workingDir, + oid: entry.oid, + }); + directories.push({ path: fullDocPath, entries: tree }); } - else { - const entryPath = entry!.path(); - - const docType: DocType = entryPath.endsWith('.json') ? 'json' : 'text'; - // eslint-disable-next-line max-depth - if (docType === 'text') { - // TODO: select binary or text by .gitattribtues - } - - let docMetadata: DocMetadata; - // eslint-disable-next-line max-depth - if (docType === 'json') { - const _id = entryPath.replace(new RegExp(JSON_EXT + '$'), ''); - docMetadata = { - _id, - name: entryPath, - fileOid: entry!.id().tostrS(), - type: 'json', - }; - } - else if (docType === 'text') { - docMetadata = { - name: entryPath, - fileOid: entry!.id().tostrS(), - type: 'text', - }; - } - else if (docType === 'binary') { - docMetadata = { - name: entryPath, - fileOid: entry!.id().tostrS(), - type: 'binary', - }; - } - - files.push(docMetadata!); + } + else { + // eslint-disable-next-line no-await-in-loop + const readBlobResult = await readBlob({ + fs, + dir: workingDir, + oid: commitOid, + filepath: fullDocPath, + }).catch(() => undefined); + + // Skip if cannot read + if (readBlobResult === undefined) continue; + + const docType: DocType = serializeFormat.hasObjectExtension(fullDocPath) + ? 'json' + : 'text'; + if (docType === 'text') { + // TODO: select binary or text by .gitattribtues + } + if (docType === 'json') { + const _id = serializeFormat.removeExtension(fullDocPath); + const meta: JsonDocMetadata = { + _id, + name: fullDocPath, + fileOid: entry.oid, + type: 'json', + }; + docs.push(meta); + } + else if (docType === 'text') { + const meta: TextDocMetadata = { + name: fullDocPath, + fileOid: entry.oid, + type: 'text', + }; + docs.push(meta); + } + else if (docType === 'binary') { + const meta: BinaryDocMetadata = { + name: fullDocPath, + fileOid: entry.oid, + type: 'binary', + }; + docs.push(meta); } } } } - return files; + + return docs; } /** diff --git a/src/validator.ts b/src/validator.ts index 3c69e800..7deb404e 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -66,6 +66,7 @@ export class Validator { static maxWorkingDirectoryLength () { // Trailing slash of workingDirectory is omitted. // Full path is `${_workingDirectory}/a.json` + // Don't care about '.md' for simplicity. const minimumMemberLength = 7; // '/a.json' return MAX_FILE_PATH_LENGTH - minimumMemberLength; } @@ -77,6 +78,7 @@ export class Validator { // Suppose that collectionPath is normalized. // Trailing slash of workingDirectory is omitted. // Full path is `${_workingDirectory}/${collectionPath}${shortId}.json` + // Don't care about '.md' for simplicity. const minIdLength = 6; // 'a.json' return MAX_FILE_PATH_LENGTH - this._workingDirectory.length - 1 - minIdLength; } @@ -91,6 +93,7 @@ export class Validator { // Suppose that collectionPath is normalized. // Trailing slash of workingDirectory is omitted. // Full path is `${_workingDirectory}/${collectionPath}${shortId}.json` + // Don't care about '.md' for simplicity. const extLength = 5; // '.json' return MAX_FILE_PATH_LENGTH - this._workingDirectory.length - 1 - extLength; } diff --git a/test/collection.test.ts b/test/collection.test.ts index cee8c969..5dae268d 100644 --- a/test/collection.test.ts +++ b/test/collection.test.ts @@ -11,6 +11,7 @@ import path from 'path'; import expect from 'expect'; import fs from 'fs-extra'; import { monotonicFactory } from 'ulid'; +import { hmtid } from 'hmtid'; import { GitDocumentDB } from '../src/git_documentdb'; import { Err } from '../src/error'; import { Collection } from '../src/collection'; @@ -79,6 +80,34 @@ describe('', () => { await gitDDB.destroy(); }); + describe('generates ID', () => { + it('using default ulid', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const col = new Collection(gitDDB, 'col01'); + expect(col.generateId(1469918176385).startsWith('01ARYZ6S41')).toBeTruthy(); + await gitDDB.destroy(); + }); + + it('using hmtid', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + idGenerator: hmtid, + }); + await gitDDB.open(); + expect( + gitDDB.rootCollection.generateId(1469918176385).startsWith('20160730223616') + ).toBeTruthy(); + await gitDDB.destroy(); + }); + }); + describe('parent', () => { it('sets parent', async () => { const dbName = monoId(); @@ -148,6 +177,26 @@ describe('', () => { await gitDDB.destroy(); }); + + it('idGenerator option is inherited by child', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + + const root = await gitDDB.collection('', { idGenerator: hmtid }); + const col01 = await root.collection('col01'); + const col02 = await col01.collection('col02'); + + expect(gitDDB.rootCollection.generateId().length).toBe(26); // length of ulid + expect(root.generateId().length).toBe(22); // length of hmtid + expect(col01.generateId().length).toBe(22); + expect(col02.generateId().length).toBe(22); + + await gitDDB.destroy(); + }); }); describe('getCollections()', () => { diff --git a/test/collection_delete.test.ts b/test/collection_delete.test.ts index 67b6351c..4fd1bf03 100644 --- a/test/collection_delete.test.ts +++ b/test/collection_delete.test.ts @@ -13,7 +13,12 @@ import git from 'isomorphic-git'; import expect from 'expect'; import { monotonicFactory } from 'ulid'; import { DeleteResultJsonDoc } from '../src/types'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../src/const'; +import { + FRONT_MATTER_POSTFIX, + JSON_POSTFIX, + SHORT_SHA_LENGTH, + YAML_POSTFIX, +} from '../src/const'; import { toSortedJSONString } from '../src/utils'; import { GitDocumentDB } from '../src/git_documentdb'; import { Err } from '../src/error'; @@ -104,7 +109,7 @@ describe('delete(shortId)', () => { expect(deleteResult._id).toBe(_id); expect(deleteResult.fileOid).toBe(putResult.fileOid); expect(deleteResult.commit.message).toBe( - `delete: users/${_id}${JSON_EXT}(${shortOid})` + `delete: users/${_id}${JSON_POSTFIX}(${shortOid})` ); // Check commit directly @@ -114,7 +119,7 @@ describe('delete(shortId)', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`delete: users/${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`delete: users/${_id}${JSON_POSTFIX}(${shortOid})\n`); await expect(users.delete(_id)).rejects.toThrowError(Err.DocumentNotFoundError); await expect(users.get(_id)).resolves.toBeUndefined(); @@ -153,7 +158,7 @@ describe('delete(shortId)', () => { expect(deleteResult._id).toBe(_id); expect(deleteResult.fileOid).toBe(putResult.fileOid); expect(deleteResult.commit.message).toBe( - `delete: ${users.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `delete: ${users.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); // Check commit directly @@ -164,7 +169,7 @@ describe('delete(shortId)', () => { oid: commitOid, }); expect(commit.message).toEqual( - `delete: ${users.collectionPath}${_id}${JSON_EXT}(${shortOid})\n` + `delete: ${users.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})\n` ); await expect(users.delete(_id)).rejects.toThrowError(Err.DocumentNotFoundError); @@ -213,6 +218,72 @@ describe('delete(shortId)', () => { await gitDDB.destroy(); }); + + describe('with front-matter', () => { + it('delete .md', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const users = new Collection(gitDDB, 'users'); + const json = { _id: 'foo', name: 'var', _body: 'baz' }; + const putResult = await users.put(json); // save .md + const shortOid = putResult.fileOid.substr(0, SHORT_SHA_LENGTH); + // @ts-ignore + const deleteResult: DeleteResultJsonDoc = await users.delete('foo'); + expect(deleteResult._id).toBe(json._id); + expect(deleteResult.fileOid).toBe(putResult.fileOid); + expect(deleteResult.commit.message).toBe( + `delete: users/${json._id}${FRONT_MATTER_POSTFIX}(${shortOid})` + ); + await gitDDB.destroy(); + }); + + it('delete .yml by fallback', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const users = new Collection(gitDDB, 'users'); + const json = { _id: 'foo', name: 'var' }; + const putResult = await users.put(json); // save .yml + const shortOid = putResult.fileOid.substr(0, SHORT_SHA_LENGTH); + // @ts-ignore + const deleteResult: DeleteResultJsonDoc = await users.delete('foo'); + expect(deleteResult._id).toBe(json._id); + expect(deleteResult.fileOid).toBe(putResult.fileOid); + expect(deleteResult.commit.message).toBe( + `delete: users/${json._id}${YAML_POSTFIX}(${shortOid})` + ); + await gitDDB.destroy(); + }); + + it('throws DocumentNotFoundError', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const users = new Collection(gitDDB, 'users'); + // @ts-ignore + await expect(users.delete({ _id: 'Shirase' })).rejects.toThrowError( + Err.DocumentNotFoundError + ); + + await gitDDB.destroy(); + }); + }); }); describe('delete(jsonDoc)', () => { @@ -248,7 +319,10 @@ describe('delete(jsonDoc)', () => { // Check NormalizedCommit expect(deleteResult.commit.oid).toBe(currentCommitOid); expect(deleteResult.commit.message).toBe( - `delete: ${users.collectionPath}${_id}${JSON_EXT}(${oid.substr(0, SHORT_SHA_LENGTH)})` + `delete: ${users.collectionPath}${_id}${JSON_POSTFIX}(${oid.substr( + 0, + SHORT_SHA_LENGTH + )})` ); expect(deleteResult.commit.parent).toEqual([prevCommitOid]); expect(deleteResult.commit.author.name).toEqual(gitDDB.author.name); @@ -316,11 +390,13 @@ describe('deleteFatDoc(name)', () => { const shortOid = putResult.fileOid.substr(0, SHORT_SHA_LENGTH); // Delete - const deleteResult = (await users.deleteFatDoc(_id + JSON_EXT)) as DeleteResultJsonDoc; + const deleteResult = (await users.deleteFatDoc( + _id + JSON_POSTFIX + )) as DeleteResultJsonDoc; expect(deleteResult._id).toBe(_id); expect(deleteResult.fileOid).toBe(putResult.fileOid); expect(deleteResult.commit.message).toBe( - `delete: users/${_id}${JSON_EXT}(${shortOid})` + `delete: users/${_id}${JSON_POSTFIX}(${shortOid})` ); // Check commit directly @@ -330,7 +406,7 @@ describe('deleteFatDoc(name)', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`delete: users/${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`delete: users/${_id}${JSON_POSTFIX}(${shortOid})\n`); await expect(users.delete(_id)).rejects.toThrowError(Err.DocumentNotFoundError); await expect(users.get(_id)).resolves.toBeUndefined(); @@ -365,11 +441,13 @@ describe('deleteFatDoc(name)', () => { const shortOid = putResult.fileOid.substr(0, SHORT_SHA_LENGTH); // Delete - const deleteResult = (await users.deleteFatDoc(_id + JSON_EXT)) as DeleteResultJsonDoc; + const deleteResult = (await users.deleteFatDoc( + _id + JSON_POSTFIX + )) as DeleteResultJsonDoc; expect(deleteResult._id).toBe(_id); expect(deleteResult.fileOid).toBe(putResult.fileOid); expect(deleteResult.commit.message).toBe( - `delete: ${users.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `delete: ${users.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); // Check commit directly @@ -380,7 +458,7 @@ describe('deleteFatDoc(name)', () => { oid: commitOid, }); expect(commit.message).toEqual( - `delete: ${users.collectionPath}${_id}${JSON_EXT}(${shortOid})\n` + `delete: ${users.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})\n` ); await expect(users.delete(_id)).rejects.toThrowError(Err.DocumentNotFoundError); diff --git a/test/collection_find.test.ts b/test/collection_find.test.ts index deba1746..deeb5ffd 100644 --- a/test/collection_find.test.ts +++ b/test/collection_find.test.ts @@ -13,7 +13,7 @@ import git from 'isomorphic-git'; import expect from 'expect'; import { monotonicFactory } from 'ulid'; import { Collection } from '../src/collection'; -import { JSON_EXT } from '../src/const'; +import { JSON_POSTFIX } from '../src/const'; import { toSortedJSONString } from '../src/utils'; import { GitDocumentDB } from '../src/git_documentdb'; import { Err } from '../src/error'; @@ -70,7 +70,7 @@ describe('', () => { const col = new Collection(gitDDB, 'col01'); await addOneData( gitDDB, - col.collectionPath + 'invalidJSON' + JSON_EXT, + col.collectionPath + 'invalidJSON' + JSON_POSTFIX, 'invalidJSON' ); @@ -117,27 +117,27 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -180,37 +180,37 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c000 + JSON_EXT, + col.collectionPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - col.collectionPath + _id_c001 + JSON_EXT, + col.collectionPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -248,37 +248,37 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c000 + JSON_EXT, + col.collectionPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - col.collectionPath + _id_c001 + JSON_EXT, + col.collectionPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -319,37 +319,37 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c000 + JSON_EXT, + col.collectionPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - col.collectionPath + _id_c001 + JSON_EXT, + col.collectionPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -392,37 +392,37 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c000 + JSON_EXT, + col.collectionPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - col.collectionPath + _id_c001 + JSON_EXT, + col.collectionPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -460,37 +460,37 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c000 + JSON_EXT, + col.collectionPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - col.collectionPath + _id_c001 + JSON_EXT, + col.collectionPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -531,43 +531,43 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_p + JSON_EXT, + col.collectionPath + _id_p + JSON_POSTFIX, toSortedJSONString(json_p) ); await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c000 + JSON_EXT, + col.collectionPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - col.collectionPath + _id_c001 + JSON_EXT, + col.collectionPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -608,43 +608,43 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_p + JSON_EXT, + col.collectionPath + _id_p + JSON_POSTFIX, toSortedJSONString(json_p) ); await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c000 + JSON_EXT, + col.collectionPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - col.collectionPath + _id_c001 + JSON_EXT, + col.collectionPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); @@ -681,62 +681,62 @@ describe('', () => { await addOneData( gitDDB, - col.collectionPath + _id_b + JSON_EXT, + col.collectionPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b) ); await addOneData( gitDDB, - col.collectionPath + _id_a + JSON_EXT, + col.collectionPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a) ); await addOneData( gitDDB, - col.collectionPath + _id_d + JSON_EXT, + col.collectionPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d) ); await addOneData( gitDDB, - col.collectionPath + _id_c01 + JSON_EXT, + col.collectionPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - col.collectionPath + _id_c02 + JSON_EXT, + col.collectionPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); await expect(col.findFatDoc()).resolves.toEqual([ { _id: _id_a, - name: _id_a + JSON_EXT, + name: _id_a + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_a) })).oid, type: 'json', doc: json_a_, }, { _id: _id_b, - name: _id_b + JSON_EXT, + name: _id_b + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_b) })).oid, type: 'json', doc: json_b_, }, { _id: _id_c01, - name: _id_c01 + JSON_EXT, + name: _id_c01 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c01) })).oid, type: 'json', doc: json_c01_, }, { _id: _id_c02, - name: _id_c02 + JSON_EXT, + name: _id_c02 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c02) })).oid, type: 'json', doc: json_c02_, }, { _id: _id_d, - name: _id_d + JSON_EXT, + name: _id_d + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_d) })).oid, type: 'json', doc: json_d_, diff --git a/test/collection_get.test.ts b/test/collection_get.test.ts index a4531e8f..9e2b4c28 100644 --- a/test/collection_get.test.ts +++ b/test/collection_get.test.ts @@ -12,9 +12,9 @@ import fs from 'fs-extra'; import git from 'isomorphic-git'; import expect from 'expect'; import { monotonicFactory } from 'ulid'; -import { JSON_EXT } from '../src/const'; +import { FRONT_MATTER_POSTFIX, JSON_POSTFIX, YAML_POSTFIX } from '../src/const'; import { Collection } from '../src/collection'; -import { sleep, toSortedJSONString } from '../src/utils'; +import { sleep, toFrontMatterMarkdown, toSortedJSONString, toYAML } from '../src/utils'; import { GitDocumentDB } from '../src/git_documentdb'; import { Err } from '../src/error'; import { addOneData, removeOneData } from './utils'; @@ -59,18 +59,6 @@ describe(' get()', () => { await gitDDB.destroy(); }); - it('throws RepositoryNotOpenError', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const col = new Collection(gitDDB, 'col01'); - await gitDDB.close(); - await expect(col.get('prof01')).rejects.toThrowError(Err.RepositoryNotOpenError); - }); - it('throws InvalidJsonObjectError', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -81,7 +69,7 @@ describe(' get()', () => { const col = new Collection(gitDDB, 'col01'); const shortId = 'prof01'; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; await addOneData(gitDDB, fullDocPath, 'invalid data'); await expect(col.get(shortId)).rejects.toThrowError(Err.InvalidJsonObjectError); @@ -98,7 +86,7 @@ describe(' get()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01'); const shortId = 'prof01'; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; const json02 = { _id: shortId, name: 'v2' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -131,7 +119,7 @@ describe(' get()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01'); const shortId = 'prof01'; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); await removeOneData(gitDDB, fullDocPath); @@ -149,7 +137,7 @@ describe(' get()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01/col02/col03/'); const shortId = 'dir01/prof01'; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -166,7 +154,7 @@ describe(' get()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'dir01/dir02/dir03'); const shortId = 'prof01'; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -174,6 +162,94 @@ describe(' get()', () => { await expect(col.get(shortId, 'invalid')).resolves.toEqual(json01); await gitDDB.destroy(); }); + + describe('with front-matter', () => { + it('returns front-matter', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const shortId = 'foo'; + const shortName = shortId + FRONT_MATTER_POSTFIX; + const fullDocPath = shortName; + const json = { _id: shortId, name: 'var', _body: 'baz' }; + await addOneData(gitDDB, fullDocPath, toFrontMatterMarkdown(json)); // save foo.md + + await expect(gitDDB.get(shortId)).resolves.toEqual(json); + + await gitDDB.destroy(); + }); + + it('returns foo.yml', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const shortId = 'foo'; + const shortNameYAML = shortId + YAML_POSTFIX; + const fullDocPathYAML = shortNameYAML; + const jsonYAML = { _id: shortId, name: 'Shirase' }; + await addOneData(gitDDB, fullDocPathYAML, toYAML(jsonYAML)); // save foo.yml + + await expect(gitDDB.get(shortId)).resolves.toEqual(jsonYAML); + + await gitDDB.destroy(); + }); + + it('returns foo.md if both foo.md and foo.yml exist', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const shortId = 'foo'; + const shortNameYAML = shortId + YAML_POSTFIX; + const fullDocPathYAML = shortNameYAML; + const jsonYAML = { _id: shortId, name: 'Shirase' }; + await addOneData(gitDDB, fullDocPathYAML, toYAML(jsonYAML)); // save foo.yml + + const shortNameMD = shortId + FRONT_MATTER_POSTFIX; + const fullDocPathMD = shortNameMD; + const jsonMD = { _id: shortId, name: 'Shirase', _body: 'var' }; + await addOneData(gitDDB, fullDocPathMD, toFrontMatterMarkdown(jsonMD)); // save foo.md + + await expect(gitDDB.get(shortId)).resolves.toEqual(jsonMD); + + await gitDDB.destroy(); + }); + + it('returns _body with _id when .md does not have front matter', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const shortId = 'foo'; + const shortNameMD = shortId + '.md'; + const fullDocPathMD = shortNameMD; + const md = 'Hello'; + const jsonMD = { _id: 'foo', _body: md }; + await addOneData(gitDDB, fullDocPathMD, md); // save foo.md + + await expect(gitDDB.get(shortId)).resolves.toEqual(jsonMD); + + await gitDDB.destroy(); + }); + }); }); describe(' getFatDoc()', () => { @@ -186,8 +262,8 @@ describe(' getFatDoc()', () => { await gitDDB.open(); const col = new Collection(gitDDB); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; const json02 = { _id: shortId, name: 'v2' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -212,7 +288,7 @@ describe(' getFatDoc()', () => { await gitDDB.open(); const col = new Collection(gitDDB); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; await expect(col.getFatDoc(shortName)).resolves.toBeUndefined(); await gitDDB.destroy(); @@ -229,7 +305,7 @@ describe(' getDocByOid()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01/col02/col03/'); const shortId = 'dir01/prof01'; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); const { oid } = await git.hashBlob({ object: toSortedJSONString(json01) }); @@ -246,7 +322,7 @@ describe(' getDocByOid()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01/col02/col03/'); const shortId = 'dir01/prof01'; - const fullDocPath = col.collectionPath + shortId + JSON_EXT; + const fullDocPath = col.collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); await expect(col.getDocByOid('not exist', 'json')).resolves.toBeUndefined(); @@ -262,7 +338,7 @@ describe(' getDocByOid()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01/col02/col03/'); const shortId = 'dir01/prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const fullDocPath = col.collectionPath + shortName; // JsonDoc without _id const json01 = { name: 'v1' }; @@ -281,10 +357,10 @@ describe('', () => { }); const targetId = '01'; - const targetName = targetId + JSON_EXT; + const targetName = targetId + JSON_POSTFIX; const collectionPath = 'col01/'; const col = new Collection(gitDDB, collectionPath); - const fullDocPath = collectionPath + targetId + JSON_EXT; + const fullDocPath = collectionPath + targetId + JSON_POSTFIX; const json01 = { _id: collectionPath + targetId, name: 'v01' }; const json02 = { _id: collectionPath + targetId, name: 'v02' }; @@ -732,7 +808,7 @@ describe(' getFatDocHistory()', () => { const col = new Collection(gitDDB, 'col01'); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -740,7 +816,7 @@ describe(' getFatDocHistory()', () => { await col.put(jsonA02); await col.put(jsonA03); const _idB = 'profB'; - const shortNameB = _idB + JSON_EXT; + const shortNameB = _idB + JSON_POSTFIX; const jsonB01 = { _id: _idB, name: 'v01' }; const jsonB02 = { _id: _idB, name: 'v02' }; await col.put(jsonB01); @@ -769,7 +845,7 @@ describe(' getFatDocHistory()', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01'); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -784,7 +860,7 @@ describe(' getFatDocHistory()', () => { await col.put(jsonA03); const _idB = 'profB'; - const shortNameB = _idB + JSON_EXT; + const shortNameB = _idB + JSON_POSTFIX; const jsonB01 = { _id: _idB, name: 'v01' }; const jsonB02 = { _id: _idB, name: 'v02' }; @@ -857,21 +933,6 @@ describe(' getFatDocHistory()', () => { await gitDDB.destroy(); }); - it('throws RepositoryNotOpenError', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const col = new Collection(gitDDB, 'col01'); - await gitDDB.close(); - await expect(col.getFatDocHistory('tmp')).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.destroy(); - }); - it('throws InvalidJsonObjectError.', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ diff --git a/test/collection_insert.test.ts b/test/collection_insert.test.ts index f1595dab..cc0a3554 100644 --- a/test/collection_insert.test.ts +++ b/test/collection_insert.test.ts @@ -14,7 +14,7 @@ import expect from 'expect'; import { monotonicFactory } from 'ulid'; import { PutResultJsonDoc } from '../src/types'; import { Collection } from '../src/collection'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../src/const'; +import { JSON_POSTFIX, SHORT_SHA_LENGTH } from '../src/const'; import { toSortedJSONString } from '../src/utils'; import { GitDocumentDB } from '../src/git_documentdb'; import { Err } from '../src/error'; @@ -87,7 +87,7 @@ describe(' insert(jsonDoc)', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -101,7 +101,11 @@ describe(' insert(jsonDoc)', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -145,7 +149,7 @@ describe(' insert(jsonDoc)', () => { const fileOid = (await git.hashBlob({ object: toSortedJSONString(internalJson) })).oid; const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); await gitDDB.destroy(); @@ -204,7 +208,7 @@ describe(' insert(shortId, jsonDoc)', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -218,7 +222,11 @@ describe(' insert(shortId, jsonDoc)', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -264,7 +272,7 @@ describe(' insertFatDoc(shortName, jsonDoc)', () => { const col = new Collection(gitDDB, 'col01'); const _id = 'prof01'; - const shortName = _id + JSON_EXT; + const shortName = _id + JSON_POSTFIX; const json = { _id, name: 'Shirase' }; const internalJson = JSON.parse(JSON.stringify(json)); internalJson._id = col.collectionPath + _id; @@ -286,7 +294,7 @@ describe(' insertFatDoc(shortName, jsonDoc)', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -300,7 +308,11 @@ describe(' insertFatDoc(shortName, jsonDoc)', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); diff --git a/test/collection_put.test.ts b/test/collection_put.test.ts index 434294a1..a92e591e 100644 --- a/test/collection_put.test.ts +++ b/test/collection_put.test.ts @@ -12,9 +12,10 @@ import git from 'isomorphic-git'; import expect from 'expect'; import fs from 'fs-extra'; import { monotonicFactory } from 'ulid'; +import { hmtid } from 'hmtid'; import { PutResultJsonDoc } from '../src/types'; import { toSortedJSONString } from '../src/utils'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../src/const'; +import { JSON_POSTFIX, SHORT_SHA_LENGTH } from '../src/const'; import { GitDocumentDB } from '../src/git_documentdb'; import { Err } from '../src/error'; import { Collection } from '../src/collection'; @@ -247,12 +248,16 @@ describe('', () => { oid: commitOid, }); expect(commit.message).toEqual( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})\n` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})\n` ); // Check filename // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); // Read JSON and check doc._id expect(fs.readJSONSync(filePath)._id).toBe(col.collectionPath + _id); @@ -298,7 +303,7 @@ describe('', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -312,7 +317,11 @@ describe('', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -337,7 +346,7 @@ describe('', () => { .oid; const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); await gitDDB.destroy(); @@ -361,7 +370,7 @@ describe('', () => { // fs.access() throw error when a file cannot be accessed. const filePath = path.resolve( gitDDB.workingDir, - col.collectionPath + _id + JSON_EXT + col.collectionPath + _id + JSON_POSTFIX ); await expect(fs.access(filePath)).resolves.not.toThrowError(); // Read JSON and check doc._id @@ -387,14 +396,14 @@ describe('', () => { await git.hashBlob({ object: toSortedJSONString(internalJson) }) ).oid.substr(0, SHORT_SHA_LENGTH); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); // Check filename // fs.access() throw error when a file cannot be accessed. const filePath = path.resolve( gitDDB.workingDir, - col.collectionPath + _id + JSON_EXT + col.collectionPath + _id + JSON_POSTFIX ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -411,7 +420,7 @@ describe('', () => { oid: commitOid, }); expect(commit.message).toEqual( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})\n` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})\n` ); gitDDB.destroy(); @@ -497,7 +506,7 @@ describe('', () => { const putResult = await col.put(updatedJson); expect(putResult.commit.message).toBe( - `update: ${col.collectionPath}${_id}${JSON_EXT}(${fileOid.substr( + `update: ${col.collectionPath}${_id}${JSON_POSTFIX}(${fileOid.substr( 0, SHORT_SHA_LENGTH )})` @@ -586,6 +595,31 @@ describe('', () => { await gitDDB.destroy(); }); + it('generates new _id with namePrefix by hmtid', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const namePrefix = 'item'; + const col = new Collection(gitDDB, 'col01', undefined, { + namePrefix, + idGenerator: hmtid, + }); + const json = { name: 'Shirase' }; + const putResult = await col.put(undefined, json); + expect(putResult._id.startsWith(namePrefix)).toBeTruthy(); + const autoGen = putResult._id.replace(namePrefix, ''); + expect(autoGen).toMatch(/^\d{14}_[\dA-HJKMNP-TV-Z]{7}$/); // Match hmtid + await expect(col.get(putResult._id)).resolves.toEqual({ + ...json, + _id: putResult._id, + }); + + await gitDDB.destroy(); + }); + it('creates a JSON file', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -624,7 +658,7 @@ describe('', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -638,7 +672,11 @@ describe('', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -693,14 +731,14 @@ describe('', () => { expect(putResult._id).toBe(_id); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); // _id of original json must not be overwritten expect(json._id).toBe('id-in-doc'); // fs.access() throw error when a file cannot be accessed. - const fullDocPath = col.collectionPath + _id + JSON_EXT; + const fullDocPath = col.collectionPath + _id + JSON_POSTFIX; const filePath = path.resolve(gitDDB.workingDir, fullDocPath); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -728,7 +766,10 @@ describe('', () => { 'A': 'A', }); - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath + 'id' + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath + 'id' + JSON_POSTFIX + ); const jsonStr = fs.readFileSync(filePath, 'utf8'); expect(jsonStr).toBe(`{ "1": 1, @@ -771,7 +812,7 @@ describe('', () => { const filePath = path.resolve( gitDDB.workingDir, col.collectionPath, - putResult._id + JSON_EXT + putResult._id + JSON_POSTFIX ); await expect(fs.access(filePath)).resolves.not.toThrowError(); @@ -809,7 +850,7 @@ describe('', () => { const col = new Collection(gitDDB, 'col01'); const _id = 'dir01/prof01'; - const shortName = _id + JSON_EXT; + const shortName = _id + JSON_POSTFIX; // Check put operation const json = { _id, name: 'Shirase' }; @@ -833,7 +874,7 @@ describe('', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `insert: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `insert: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -847,7 +888,11 @@ describe('', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); diff --git a/test/collection_update.test.ts b/test/collection_update.test.ts index 8e997d50..434ef251 100644 --- a/test/collection_update.test.ts +++ b/test/collection_update.test.ts @@ -17,7 +17,7 @@ import { Err } from '../src/error'; import { GitDocumentDB } from '../src/git_documentdb'; import { Collection } from '../src/collection'; import { toSortedJSONString } from '../src/utils'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../src/const'; +import { JSON_POSTFIX, SHORT_SHA_LENGTH } from '../src/const'; const ulid = monotonicFactory(); const monoId = () => { @@ -85,7 +85,7 @@ describe(' update(jsonDoc)', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `update: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `update: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -99,7 +99,11 @@ describe(' update(jsonDoc)', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -147,7 +151,7 @@ describe(' update(jsonDoc)', () => { const fileOid = (await git.hashBlob({ object: toSortedJSONString(internalJson) })).oid; const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult.commit.message).toBe( - `update: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `update: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); await gitDDB.destroy(); @@ -204,7 +208,7 @@ describe(' update(shortId, jsonDoc)', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `update: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `update: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -218,7 +222,11 @@ describe(' update(shortId, jsonDoc)', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); @@ -259,7 +267,7 @@ describe(' updateFatDoc(shortName, jsonDoc)', () => { await gitDDB.open(); const col = new Collection(gitDDB, 'col01'); const _id = 'prof01'; - const shortName = _id + JSON_EXT; + const shortName = _id + JSON_POSTFIX; const json = { _id, name: 'Shirase' }; const insertResult = await col.insert(json); @@ -286,7 +294,7 @@ describe(' updateFatDoc(shortName, jsonDoc)', () => { expect(putResult.fileOid).toBe(fileOid); expect(putResult.commit.oid).toBe(currentCommitOid); expect(putResult.commit.message).toBe( - `update: ${col.collectionPath}${_id}${JSON_EXT}(${shortOid})` + `update: ${col.collectionPath}${_id}${JSON_POSTFIX}(${shortOid})` ); expect(putResult.commit.parent).toEqual([prevCommitOid]); @@ -300,7 +308,11 @@ describe(' updateFatDoc(shortName, jsonDoc)', () => { expect(putResult.commit.committer.timestamp).toBeLessThanOrEqual(afterTimestamp); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, col.collectionPath, _id + JSON_EXT); + const filePath = path.resolve( + gitDDB.workingDir, + col.collectionPath, + _id + JSON_POSTFIX + ); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(internalJson)); diff --git a/test/crud/blob.test.ts b/test/crud/blob.test.ts index ef58f97f..a68ea321 100644 --- a/test/crud/blob.test.ts +++ b/test/crud/blob.test.ts @@ -23,8 +23,17 @@ import { } from '../../src/crud/blob'; import { Err } from '../../src/error'; import { GitDocumentDB } from '../../src/git_documentdb'; -import { toSortedJSONString, utf8encode } from '../../src/utils'; -import { JSON_EXT } from '../../src/const'; +import { + toFrontMatterMarkdown, + toSortedJSONString, + toYAML, + utf8encode, +} from '../../src/utils'; +import { FRONT_MATTER_POSTFIX, JSON_POSTFIX, YAML_POSTFIX } from '../../src/const'; +import { + SerializeFormatFrontMatter, + SerializeFormatJSON, +} from '../../src/serialize_format'; // eslint-disable-next-line @typescript-eslint/no-var-requires const git_module = require('isomorphic-git'); @@ -61,9 +70,15 @@ describe('', () => { oid: (await git.hashBlob({ object: text })).oid, blob: utf8encode(text), }; - expect(() => blobToJsonDoc(shortId, readBlobResult, false)).toThrowError( - Err.InvalidJsonObjectError - ); + expect(() => + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatJSON(), + JSON_POSTFIX + ) + ).toThrowError(Err.InvalidJsonObjectError); }); it('returns JsonDoc', async () => { @@ -74,7 +89,207 @@ describe('', () => { oid: (await git.hashBlob({ object: text })).oid, blob: utf8encode(text), }; - expect(blobToJsonDoc(shortId, readBlobResult, false)).toEqual(json); + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatJSON(), + JSON_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc with only _id when YAML_POSTFIX and Front-Matter + Markdown is empty', async () => { + const shortId = 'foo'; + const text = ''; + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + YAML_POSTFIX + ) + ).toEqual({ + _id: 'foo', + }); + }); + + it('returns JsonDoc with only _id and _body when FRONT_MATTER_POSTFIX and Front-Matter + Markdown is empty', async () => { + const shortId = 'foo'; + const text = ''; + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual({ + _id: 'foo', + _body: '', + }); + }); + + it('returns JsonDoc with only _id and _body when Front-Matter is empty', async () => { + const shortId = 'foo'; + const text = 'bar\nbaz'; + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual({ + _id: 'foo', + _body: text, + }); + }); + + it('returns JsonDoc with only _id and _body when Front-Matter does not end', async () => { + const shortId = 'foo'; + const text = '---\na: foo'; + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual({ + _id: 'foo', + _body: text, + }); + }); + + it('returns JsonDoc of Front-Matter + Markdown', async () => { + const shortId = 'foo'; + const json = { _id: shortId, propA: 'A', propB: 'B', _body: 'foo\nbar' }; + const text = toFrontMatterMarkdown(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc of Front-Matter + Markdown when _body is empty', async () => { + const shortId = 'foo'; + const json = { _id: shortId, propA: 'A', propB: 'B', _body: '' }; + const text = toFrontMatterMarkdown(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc of Front-Matter + Markdown that ends with \n', async () => { + const shortId = 'foo'; + const json = { _id: shortId, propA: 'A', propB: 'B', _body: 'foo\nbar\n' }; + const text = toFrontMatterMarkdown(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc of Front-Matter and Markdown witch stats with ---', async () => { + const shortId = 'foo'; + const json = { _id: shortId, propA: 'A', propB: 'B', _body: '---\nfoo\nbar' }; + const text = toFrontMatterMarkdown(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc of YAML without Markdown', async () => { + const shortId = 'foo'; + const json = { _id: shortId, propA: 'A', propB: 'B' }; + const text = toYAML(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc( + shortId, + readBlobResult, + false, + new SerializeFormatFrontMatter(), + YAML_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc of Markdown when file extension is unknown', async () => { + const shortId = 'foo'; + const json = { _id: shortId, propA: 'A', propB: 'B' }; + const jsonMarkdown = { _id: shortId, _body: '_id: foo\npropA: A\npropB: B\n' }; + const text = toYAML(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDoc(shortId, readBlobResult, false, new SerializeFormatFrontMatter(), '') + ).toEqual(jsonMarkdown); }); it('returns JsonDoc with overwritten _id', async () => { @@ -87,7 +302,15 @@ describe('', () => { oid: (await git.hashBlob({ object: text })).oid, blob: utf8encode(text), }; - expect(blobToJsonDoc(shortId2, readBlobResult, false)).toEqual(json2); + expect( + blobToJsonDoc( + shortId2, + readBlobResult, + false, + new SerializeFormatJSON(), + JSON_POSTFIX + ) + ).toEqual(json2); }); it('returns FatJsonDoc', async () => { @@ -99,9 +322,17 @@ describe('', () => { oid: fileOid, blob: utf8encode(text), }; - expect(blobToJsonDoc(shortId, readBlobResult, true)).toEqual({ + expect( + blobToJsonDoc( + shortId, + readBlobResult, + true, + new SerializeFormatJSON(), + JSON_POSTFIX + ) + ).toEqual({ _id: shortId, - name: shortId + JSON_EXT, + name: shortId + JSON_POSTFIX, fileOid, type: 'json', doc: json, @@ -116,9 +347,13 @@ describe('', () => { oid: (await git.hashBlob({ object: text })).oid, blob: utf8encode(text), }; - expect(() => blobToJsonDocWithoutOverwrittenId(readBlobResult)).toThrowError( - Err.InvalidJsonObjectError - ); + expect(() => + blobToJsonDocWithoutOverwrittenId( + readBlobResult, + new SerializeFormatJSON(), + JSON_POSTFIX + ) + ).toThrowError(Err.InvalidJsonObjectError); }); it('returns JsonDoc', async () => { @@ -129,7 +364,65 @@ describe('', () => { oid: (await git.hashBlob({ object: text })).oid, blob: utf8encode(text), }; - expect(blobToJsonDocWithoutOverwrittenId(readBlobResult)).toEqual(json); + expect( + blobToJsonDocWithoutOverwrittenId( + readBlobResult, + new SerializeFormatJSON(), + JSON_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc in FrontMatterMarkdown', async () => { + const shortId = 'foo'; + const json = { _id: shortId, name: 'bar', _body: 'baz' }; + const text = toFrontMatterMarkdown(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDocWithoutOverwrittenId( + readBlobResult, + new SerializeFormatFrontMatter(), + FRONT_MATTER_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc in YAML', async () => { + const shortId = 'foo'; + const json = { _id: shortId, name: 'bar' }; + const text = toYAML(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDocWithoutOverwrittenId( + readBlobResult, + new SerializeFormatFrontMatter(), + YAML_POSTFIX + ) + ).toEqual(json); + }); + + it('returns JsonDoc of Markdown when shortId and file extension is unknown', async () => { + const shortId = 'foo'; + const json = { _id: shortId, propA: 'A', propB: 'B' }; + const jsonMarkdown = { _body: '_id: foo\npropA: A\npropB: B\n' }; + const text = toYAML(json); + const readBlobResult: ReadBlobResult = { + oid: (await git.hashBlob({ object: text })).oid, + blob: utf8encode(text), + }; + expect( + blobToJsonDocWithoutOverwrittenId( + readBlobResult, + new SerializeFormatFrontMatter(), + '' + ) + ).toEqual(jsonMarkdown); }); }); diff --git a/test/crud/delete.test.ts b/test/crud/delete.test.ts index a8a9c306..553754da 100644 --- a/test/crud/delete.test.ts +++ b/test/crud/delete.test.ts @@ -13,7 +13,7 @@ import fs from 'fs-extra'; import git from 'isomorphic-git'; import expect from 'expect'; import sinon from 'sinon'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../../src/const'; +import { JSON_POSTFIX, SHORT_SHA_LENGTH } from '../../src/const'; import { Err } from '../../src/error'; import { GitDocumentDB } from '../../src/git_documentdb'; import { deleteImpl, deleteWorker } from '../../src/crud/delete'; @@ -67,7 +67,7 @@ describe('', () => { // Call close() without await gitDDB.close().catch(() => {}); const _id = 'prof01'; - await expect(deleteImpl(gitDDB, '', _id, _id + JSON_EXT)).rejects.toThrowError( + await expect(deleteImpl(gitDDB, '', _id, _id + JSON_POSTFIX)).rejects.toThrowError( Err.DatabaseClosingError ); @@ -97,7 +97,7 @@ describe('', () => { } ); } - gitDDB.taskQueue.clear(); + gitDDB.taskQueue.stop(); await sleep(3000); expect(taskCancelErrorCount).toBeGreaterThan(0); await gitDDB.destroy(); @@ -116,7 +116,7 @@ describe('', () => { const putResult = await gitDDB.put(json); await expect( - deleteImpl(gitDDB, '', _id, _id + JSON_EXT + '_invalid') + deleteImpl(gitDDB, '', _id, _id + JSON_POSTFIX + '_invalid') ).rejects.toThrowError(Err.DocumentNotFoundError); await gitDDB.destroy(); @@ -139,7 +139,7 @@ describe('', () => { // Delete const { oid } = await git.hashBlob({ object: toSortedJSONString(json) }); const beforeTimestamp = Math.floor(Date.now() / 1000) * 1000; - const pickedDeleteResult = await deleteImpl(gitDDB, '', _id, _id + JSON_EXT); + const pickedDeleteResult = await deleteImpl(gitDDB, '', _id, _id + JSON_POSTFIX); const afterTimestamp = Math.floor(Date.now() / 1000) * 1000; const currentCommitOid = await git.resolveRef({ @@ -151,7 +151,7 @@ describe('', () => { // Check NormalizedCommit expect(pickedDeleteResult.commit.oid).toBe(currentCommitOid); expect(pickedDeleteResult.commit.message).toBe( - `delete: ${_id}${JSON_EXT}(${oid.substr(0, SHORT_SHA_LENGTH)})` + `delete: ${_id}${JSON_POSTFIX}(${oid.substr(0, SHORT_SHA_LENGTH)})` ); expect(pickedDeleteResult.commit.parent).toEqual([prevCommitOid]); expect(pickedDeleteResult.commit.author.name).toEqual(gitDDB.author.name); @@ -188,10 +188,10 @@ describe('', () => { // Delete const shortOid = putResult.fileOid.substr(0, SHORT_SHA_LENGTH); - const pickedDeleteResult = await deleteImpl(gitDDB, '', _id, _id + JSON_EXT); + const pickedDeleteResult = await deleteImpl(gitDDB, '', _id, _id + JSON_POSTFIX); expect(pickedDeleteResult.commit.message).toEqual( - `delete: ${_id}${JSON_EXT}(${shortOid})` + `delete: ${_id}${JSON_POSTFIX}(${shortOid})` ); // Check commit directly @@ -201,7 +201,7 @@ describe('', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`delete: ${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`delete: ${_id}${JSON_POSTFIX}(${shortOid})\n`); await gitDDB.destroy(); }); @@ -219,11 +219,13 @@ describe('', () => { const putResult = await gitDDB.put(doc); // Delete - const deleteResult = await deleteImpl(gitDDB, '', _id, _id + JSON_EXT); + const deleteResult = await deleteImpl(gitDDB, '', _id, _id + JSON_POSTFIX); const shortOid = putResult.fileOid.substr(0, SHORT_SHA_LENGTH); expect(deleteResult.fileOid).toBe(putResult.fileOid); - expect(deleteResult.commit.message).toBe(`delete: ${_id}${JSON_EXT}(${shortOid})`); + expect(deleteResult.commit.message).toBe( + `delete: ${_id}${JSON_POSTFIX}(${shortOid})` + ); // Check commit directly const commitOid = await git.resolveRef({ fs, dir: gitDDB.workingDir, ref: 'HEAD' }); @@ -232,7 +234,7 @@ describe('', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`delete: ${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`delete: ${_id}${JSON_POSTFIX}(${shortOid})\n`); await gitDDB.destroy(); }); @@ -269,17 +271,17 @@ describe('', () => { ]); await Promise.all([ - deleteImpl(gitDDB, '', _id_a, _id_a + JSON_EXT), - deleteImpl(gitDDB, '', _id_b, _id_b + JSON_EXT), - deleteImpl(gitDDB, '', _id_c01, _id_c01 + JSON_EXT), - deleteImpl(gitDDB, '', _id_c02, _id_c02 + JSON_EXT), - deleteImpl(gitDDB, '', _id_d, _id_d + JSON_EXT), + deleteImpl(gitDDB, '', _id_a, _id_a + JSON_POSTFIX), + deleteImpl(gitDDB, '', _id_b, _id_b + JSON_POSTFIX), + deleteImpl(gitDDB, '', _id_c01, _id_c01 + JSON_POSTFIX), + deleteImpl(gitDDB, '', _id_c02, _id_c02 + JSON_POSTFIX), + deleteImpl(gitDDB, '', _id_d, _id_d + JSON_POSTFIX), ]); await expect(gitDDB.findFatDoc({ recursive: true })).resolves.toEqual([ { _id: _id_p, - name: _id_p + JSON_EXT, + name: _id_p + JSON_POSTFIX, fileOid: expect.stringMatching(/^[\da-z]{40}$/), type: 'json', doc: { _id: _id_p, name: name_p }, @@ -328,18 +330,6 @@ describe('', () => { await expect(deleteWorker(undefined)).rejects.toThrowError(Err.UndefinedDBError); }); - it('throws RepositoryNotOpenError when a repository is not opened.', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await expect(deleteWorker(gitDDB, '', 'prof01', '')).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.destroy(); - }); - it('throws DocumentNotFoundError when collectionPath is undefined.', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -396,9 +386,9 @@ describe('', () => { const stubEnsureDir = sandbox.stub(fs_module, 'remove'); stubEnsureDir.rejects(); - await expect(deleteWorker(gitDDB, '', 'prof01' + JSON_EXT, '')).rejects.toThrowError( - Err.CannotDeleteDataError - ); + await expect( + deleteWorker(gitDDB, '', 'prof01' + JSON_POSTFIX, '') + ).rejects.toThrowError(Err.CannotDeleteDataError); await gitDDB.destroy(); }); }); diff --git a/test/crud/find.test.ts b/test/crud/find.test.ts index cf459d41..61f4d691 100644 --- a/test/crud/find.test.ts +++ b/test/crud/find.test.ts @@ -14,7 +14,11 @@ import { monotonicFactory } from 'ulid'; import { sleep, toSortedJSONString } from '../../src/utils'; import { Err } from '../../src/error'; import { GitDocumentDB } from '../../src/git_documentdb'; -import { FIRST_COMMIT_MESSAGE, GIT_DOCUMENTDB_INFO_ID, JSON_EXT } from '../../src/const'; +import { + FIRST_COMMIT_MESSAGE, + GIT_DOCUMENTDB_INFO_ID, + JSON_POSTFIX, +} from '../../src/const'; import { findImpl } from '../../src/crud/find'; import { addOneData } from '../utils'; @@ -76,9 +80,9 @@ describe(' find()', () => { } // Call close() without await gitDDB.close().catch(() => {}); - await expect(findImpl(gitDDB, '', true, false)).rejects.toThrowError( - Err.DatabaseClosingError - ); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).rejects.toThrowError(Err.DatabaseClosingError); while (gitDDB.isClosing) { // eslint-disable-next-line no-await-in-loop await sleep(100); @@ -86,20 +90,6 @@ describe(' find()', () => { await gitDDB.destroy(); }); - it('throws RepositoryNotOpenError', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - await gitDDB.close(); - await expect(findImpl(gitDDB, '', true, false)).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.destroy(); - }); - it('throws InvalidJsonObjectError', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -108,11 +98,11 @@ describe(' find()', () => { }); await gitDDB.open(); - await addOneData(gitDDB, 'invalidJSON' + JSON_EXT, 'invalidJSON'); + await addOneData(gitDDB, 'invalidJSON' + JSON_POSTFIX, 'invalidJSON'); - await expect(findImpl(gitDDB, '', true, false)).rejects.toThrowError( - Err.InvalidJsonObjectError - ); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).rejects.toThrowError(Err.InvalidJsonObjectError); await gitDDB.destroy(); }); @@ -125,15 +115,15 @@ describe(' find()', () => { localDir, }); - const infoPath = path.resolve(gitDDB.workingDir, GIT_DOCUMENTDB_INFO_ID + JSON_EXT); + const infoPath = path.resolve(gitDDB.workingDir, GIT_DOCUMENTDB_INFO_ID + JSON_POSTFIX); await fs.ensureDir(path.dirname(infoPath)); // Create empty repository await git.init({ fs, dir: gitDDB.workingDir, defaultBranch: 'main' }); - await fs.writeFile(infoPath, {}); + await fs.writeFile(infoPath, toSortedJSONString({})); await git.add({ fs, dir: gitDDB.workingDir, - filepath: GIT_DOCUMENTDB_INFO_ID + JSON_EXT, + filepath: GIT_DOCUMENTDB_INFO_ID + JSON_POSTFIX, }); await git.commit({ fs, @@ -147,11 +137,13 @@ describe(' find()', () => { const _id = '1'; const json = { _id }; - await addOneData(gitDDB, _id + JSON_EXT, toSortedJSONString(json)); + await addOneData(gitDDB, _id + JSON_POSTFIX, toSortedJSONString(json)); await gitDDB.open(); - await expect(findImpl(gitDDB, '', true, false)).resolves.toEqual([json]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).resolves.toEqual([json]); await gitDDB.destroy(); }); @@ -166,7 +158,9 @@ describe(' find()', () => { await gitDDB.open(); - await expect(findImpl(gitDDB, '', true, false)).resolves.toEqual([]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).resolves.toEqual([]); await gitDDB.destroy(); }); @@ -179,10 +173,6 @@ describe(' find()', () => { localDir, }); - await expect(findImpl(gitDDB, '', true, false)).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.open(); const json_b = { _id: _id_b, name: name_b }; @@ -190,17 +180,14 @@ describe(' find()', () => { const json_1 = { _id: _id_1, name: name_1 }; const json_c = { _id: _id_c, name: name_c }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_1 + JSON_EXT, toSortedJSONString(json_1)); - await addOneData(gitDDB, _id_c + JSON_EXT, toSortedJSONString(json_c)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_1 + JSON_POSTFIX, toSortedJSONString(json_1)); + await addOneData(gitDDB, _id_c + JSON_POSTFIX, toSortedJSONString(json_c)); - await expect(findImpl(gitDDB, '', true, false)).resolves.toEqual([ - json_1, - json_a, - json_b, - json_c, - ]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).resolves.toEqual([json_1, json_a, json_b, json_c]); await gitDDB.destroy(); }); @@ -219,24 +206,18 @@ describe(' find()', () => { const json_1 = { _id: _id_1, name: name_1 }; const json_c = { _id: _id_c, name: name_c }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_1 + JSON_EXT, toSortedJSONString(json_1)); - await addOneData(gitDDB, _id_c + JSON_EXT, toSortedJSONString(json_c)); - - await expect(findImpl(gitDDB, '', true, false)).resolves.toEqual([ - json_1, - json_a, - json_b, - json_c, - ]); - - await expect(findImpl(gitDDB, '', true, false, { descending: true })).resolves.toEqual([ - json_c, - json_b, - json_a, - json_1, - ]); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_1 + JSON_POSTFIX, toSortedJSONString(json_1)); + await addOneData(gitDDB, _id_c + JSON_POSTFIX, toSortedJSONString(json_c)); + + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).resolves.toEqual([json_1, json_a, json_b, json_c]); + + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { descending: true }) + ).resolves.toEqual([json_c, json_b, json_a, json_1]); await gitDDB.destroy(); }); @@ -255,19 +236,15 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); - await expect(findImpl(gitDDB, '', true, false)).resolves.toEqual([ - json_a, - json_b, - json_c01, - json_c02, - json_d, - ]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).resolves.toEqual([json_a, json_b, json_c01, json_c02, json_d]); await gitDDB.destroy(); }); @@ -287,16 +264,15 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); - await expect(findImpl(gitDDB, '', true, false, { recursive: false })).resolves.toEqual([ - json_a, - json_b, - ]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { recursive: false }) + ).resolves.toEqual([json_a, json_b]); await gitDDB.destroy(); }); @@ -309,10 +285,6 @@ describe(' find()', () => { localDir, }); - await expect(findImpl(gitDDB, '', true, false)).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.open(); const json_b = { _id: _id_b, name: name_b }; @@ -320,12 +292,14 @@ describe(' find()', () => { const json_1 = { _id: _id_1, name: name_1 }; const json_c = { _id: _id_c, name: name_c }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); await addOneData(gitDDB, _id_1, toSortedJSONString(json_1)); await addOneData(gitDDB, _id_c, toSortedJSONString(json_c)); - await expect(findImpl(gitDDB, '', true, false)).resolves.toEqual([json_a, json_b]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false) + ).resolves.toEqual([json_a, json_b]); await gitDDB.destroy(); }); @@ -347,20 +321,19 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'citrus/'; - await expect(findImpl(gitDDB, '', true, false, { prefix })).resolves.toEqual([ - json_c01, - json_c02, - ]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([json_c01, json_c02]); await gitDDB.destroy(); }); @@ -381,18 +354,21 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'cit'; await expect( - findImpl(gitDDB, '', true, false, { prefix, recursive: false }) + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { + prefix, + recursive: false, + }) ).resolves.toEqual([json_c000, json_c001]); await gitDDB.destroy(); @@ -414,22 +390,19 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'citrus'; - await expect(findImpl(gitDDB, '', true, false, { prefix })).resolves.toEqual([ - json_c000, - json_c001, - json_c01, - json_c02, - ]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([json_c000, json_c001, json_c01, json_c02]); await gitDDB.destroy(); }); @@ -450,19 +423,19 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'citrus/y'; - await expect(findImpl(gitDDB, '', true, false, { prefix })).resolves.toEqual([ - json_c02, - ]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([json_c02]); await gitDDB.destroy(); }); @@ -483,17 +456,19 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'not_exist/'; - await expect(findImpl(gitDDB, '', true, false, { prefix })).resolves.toEqual([]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([]); await gitDDB.destroy(); }); @@ -515,23 +490,23 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_p + JSON_EXT, toSortedJSONString(json_p)); + await addOneData(gitDDB, _id_p + JSON_POSTFIX, toSortedJSONString(json_p)); - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); await expect( - findImpl(gitDDB, '', true, false, { prefix: 'pear/Japan' }) + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { prefix: 'pear/Japan' }) ).resolves.toEqual([json_p]); - await expect(findImpl(gitDDB, '', true, false, { prefix: 'pear' })).resolves.toEqual([ - json_p, - ]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, false, { prefix: 'pear' }) + ).resolves.toEqual([json_p]); await gitDDB.destroy(); }); @@ -548,7 +523,9 @@ describe(' find()', () => { await gitDDB.open(); - await expect(findImpl(gitDDB, 'col01', true, false)).resolves.toEqual([]); + await expect( + findImpl(gitDDB, 'col01', gitDDB.serializeFormat, true, false) + ).resolves.toEqual([]); await gitDDB.destroy(); }); @@ -561,10 +538,6 @@ describe(' find()', () => { localDir, }); - await expect(findImpl(gitDDB, '', true, false)).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.open(); const colPath = 'col01/'; @@ -578,17 +551,14 @@ describe(' find()', () => { const json_1_ = { _id: _id_1, name: name_1 }; const json_c_ = { _id: _id_c, name: name_c }; - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_1 + JSON_EXT, toSortedJSONString(json_1)); - await addOneData(gitDDB, colPath + _id_c + JSON_EXT, toSortedJSONString(json_c)); + await addOneData(gitDDB, colPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, colPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, colPath + _id_1 + JSON_POSTFIX, toSortedJSONString(json_1)); + await addOneData(gitDDB, colPath + _id_c + JSON_POSTFIX, toSortedJSONString(json_c)); - await expect(findImpl(gitDDB, colPath, true, false)).resolves.toEqual([ - json_1_, - json_a_, - json_b_, - json_c_, - ]); + await expect( + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false) + ).resolves.toEqual([json_1_, json_a_, json_b_, json_c_]); await gitDDB.destroy(); }); @@ -614,19 +584,23 @@ describe(' find()', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, colPath + _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, colPath + _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); - - await expect(findImpl(gitDDB, colPath, true, false)).resolves.toEqual([ - json_a_, - json_b_, - json_c01_, - json_c02_, - json_d_, - ]); + await addOneData(gitDDB, colPath + _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, colPath + _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, colPath + _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData( + gitDDB, + colPath + _id_c01 + JSON_POSTFIX, + toSortedJSONString(json_c01) + ); + await addOneData( + gitDDB, + colPath + _id_c02 + JSON_POSTFIX, + toSortedJSONString(json_c02) + ); + + await expect( + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false) + ).resolves.toEqual([json_a_, json_b_, json_c01_, json_c02_, json_d_]); await gitDDB.destroy(); }); @@ -657,36 +631,47 @@ describe(' find()', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_d + JSON_EXT, toSortedJSONString(json_d)); await addOneData( gitDDB, - colPath + _id_c000 + JSON_EXT, + colPath + _id_b + JSON_POSTFIX, + toSortedJSONString(json_b) + ); + await addOneData( + gitDDB, + colPath + _id_a + JSON_POSTFIX, + toSortedJSONString(json_a) + ); + await addOneData( + gitDDB, + colPath + _id_d + JSON_POSTFIX, + toSortedJSONString(json_d) + ); + await addOneData( + gitDDB, + colPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - colPath + _id_c001 + JSON_EXT, + colPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - colPath + _id_c01 + JSON_EXT, + colPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - colPath + _id_c02 + JSON_EXT, + colPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); const prefix = 'citrus/'; - await expect(findImpl(gitDDB, colPath, true, false, { prefix })).resolves.toEqual([ - json_c01_, - json_c02_, - ]); + await expect( + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([json_c01_, json_c02_]); await gitDDB.destroy(); }); @@ -716,34 +701,49 @@ describe(' find()', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_d + JSON_EXT, toSortedJSONString(json_d)); await addOneData( gitDDB, - colPath + _id_c000 + JSON_EXT, + colPath + _id_b + JSON_POSTFIX, + toSortedJSONString(json_b) + ); + await addOneData( + gitDDB, + colPath + _id_a + JSON_POSTFIX, + toSortedJSONString(json_a) + ); + await addOneData( + gitDDB, + colPath + _id_d + JSON_POSTFIX, + toSortedJSONString(json_d) + ); + await addOneData( + gitDDB, + colPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - colPath + _id_c001 + JSON_EXT, + colPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - colPath + _id_c01 + JSON_EXT, + colPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - colPath + _id_c02 + JSON_EXT, + colPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); const prefix = 'cit'; await expect( - findImpl(gitDDB, colPath, true, false, { prefix, recursive: false }) + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false, { + prefix, + recursive: false, + }) ).resolves.toEqual([json_c000_, json_c001_]); await gitDDB.destroy(); @@ -774,38 +774,47 @@ describe(' find()', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_d + JSON_EXT, toSortedJSONString(json_d)); await addOneData( gitDDB, - colPath + _id_c000 + JSON_EXT, + colPath + _id_b + JSON_POSTFIX, + toSortedJSONString(json_b) + ); + await addOneData( + gitDDB, + colPath + _id_a + JSON_POSTFIX, + toSortedJSONString(json_a) + ); + await addOneData( + gitDDB, + colPath + _id_d + JSON_POSTFIX, + toSortedJSONString(json_d) + ); + await addOneData( + gitDDB, + colPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - colPath + _id_c001 + JSON_EXT, + colPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - colPath + _id_c01 + JSON_EXT, + colPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - colPath + _id_c02 + JSON_EXT, + colPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); const prefix = 'citrus'; - await expect(findImpl(gitDDB, colPath, true, false, { prefix })).resolves.toEqual([ - json_c000_, - json_c001_, - json_c01_, - json_c02_, - ]); + await expect( + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([json_c000_, json_c001_, json_c01_, json_c02_]); await gitDDB.destroy(); }); @@ -835,35 +844,47 @@ describe(' find()', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_d + JSON_EXT, toSortedJSONString(json_d)); await addOneData( gitDDB, - colPath + _id_c000 + JSON_EXT, + colPath + _id_b + JSON_POSTFIX, + toSortedJSONString(json_b) + ); + await addOneData( + gitDDB, + colPath + _id_a + JSON_POSTFIX, + toSortedJSONString(json_a) + ); + await addOneData( + gitDDB, + colPath + _id_d + JSON_POSTFIX, + toSortedJSONString(json_d) + ); + await addOneData( + gitDDB, + colPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - colPath + _id_c001 + JSON_EXT, + colPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - colPath + _id_c01 + JSON_EXT, + colPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - colPath + _id_c02 + JSON_EXT, + colPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); const prefix = 'citrus/y'; - await expect(findImpl(gitDDB, colPath, true, false, { prefix })).resolves.toEqual([ - json_c02_, - ]); + await expect( + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([json_c02_]); await gitDDB.destroy(); }); @@ -893,35 +914,47 @@ describe(' find()', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_d + JSON_EXT, toSortedJSONString(json_d)); await addOneData( gitDDB, - colPath + _id_c000 + JSON_EXT, + colPath + _id_b + JSON_POSTFIX, + toSortedJSONString(json_b) + ); + await addOneData( + gitDDB, + colPath + _id_a + JSON_POSTFIX, + toSortedJSONString(json_a) + ); + await addOneData( + gitDDB, + colPath + _id_d + JSON_POSTFIX, + toSortedJSONString(json_d) + ); + await addOneData( + gitDDB, + colPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - colPath + _id_c001 + JSON_EXT, + colPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - colPath + _id_c01 + JSON_EXT, + colPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - colPath + _id_c02 + JSON_EXT, + colPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); const prefix = 'not_exist/'; - await expect(findImpl(gitDDB, colPath, true, false, { prefix })).resolves.toEqual( - [] - ); + await expect( + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false, { prefix }) + ).resolves.toEqual([]); await gitDDB.destroy(); }); @@ -953,38 +986,56 @@ describe(' find()', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, colPath + _id_p + JSON_EXT, toSortedJSONString(json_p)); + await addOneData( + gitDDB, + colPath + _id_p + JSON_POSTFIX, + toSortedJSONString(json_p) + ); - await addOneData(gitDDB, colPath + _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, colPath + _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, colPath + _id_d + JSON_EXT, toSortedJSONString(json_d)); await addOneData( gitDDB, - colPath + _id_c000 + JSON_EXT, + colPath + _id_b + JSON_POSTFIX, + toSortedJSONString(json_b) + ); + await addOneData( + gitDDB, + colPath + _id_a + JSON_POSTFIX, + toSortedJSONString(json_a) + ); + await addOneData( + gitDDB, + colPath + _id_d + JSON_POSTFIX, + toSortedJSONString(json_d) + ); + await addOneData( + gitDDB, + colPath + _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000) ); await addOneData( gitDDB, - colPath + _id_c001 + JSON_EXT, + colPath + _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001) ); await addOneData( gitDDB, - colPath + _id_c01 + JSON_EXT, + colPath + _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01) ); await addOneData( gitDDB, - colPath + _id_c02 + JSON_EXT, + colPath + _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02) ); await expect( - findImpl(gitDDB, colPath, true, false, { prefix: 'pear/Japan' }) + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false, { + prefix: 'pear/Japan', + }) ).resolves.toEqual([json_p_]); await expect( - findImpl(gitDDB, colPath, true, false, { prefix: 'pear' }) + findImpl(gitDDB, colPath, gitDDB.serializeFormat, true, false, { prefix: 'pear' }) ).resolves.toEqual([json_p_]); await gitDDB.destroy(); @@ -1003,7 +1054,9 @@ describe(' find()', () => { await gitDDB.open(); - await expect(findImpl(gitDDB, '', true, true)).resolves.toEqual([]); + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, true) + ).resolves.toEqual([]); await gitDDB.destroy(); }); @@ -1022,44 +1075,46 @@ describe(' find()', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); - await expect(findImpl(gitDDB, '', true, true)).resolves.toEqual([ + await expect( + findImpl(gitDDB, '', gitDDB.serializeFormat, true, true) + ).resolves.toEqual([ { _id: _id_a, - name: _id_a + JSON_EXT, + name: _id_a + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_a) })).oid, type: 'json', doc: json_a, }, { _id: _id_b, - name: _id_b + JSON_EXT, + name: _id_b + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_b) })).oid, type: 'json', doc: json_b, }, { _id: _id_c01, - name: _id_c01 + JSON_EXT, + name: _id_c01 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c01) })).oid, type: 'json', doc: json_c01, }, { _id: _id_c02, - name: _id_c02 + JSON_EXT, + name: _id_c02 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c02) })).oid, type: 'json', doc: json_c02, }, { _id: _id_d, - name: _id_d + JSON_EXT, + name: _id_d + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_d) })).oid, type: 'json', doc: json_d, diff --git a/test/crud/get.test.ts b/test/crud/get.test.ts index 034801bc..6191e5df 100644 --- a/test/crud/get.test.ts +++ b/test/crud/get.test.ts @@ -13,11 +13,11 @@ import git from 'isomorphic-git'; import expect from 'expect'; import { monotonicFactory } from 'ulid'; import sinon from 'sinon'; -import { sleep, toSortedJSONString } from '../../src/utils'; +import { sleep, toFrontMatterMarkdown, toSortedJSONString } from '../../src/utils'; import { Err } from '../../src/error'; import { GitDocumentDB } from '../../src/git_documentdb'; import { getImpl } from '../../src/crud/get'; -import { JSON_EXT } from '../../src/const'; +import { FRONT_MATTER_POSTFIX, JSON_POSTFIX } from '../../src/const'; import { addOneData, removeOneData } from '../utils'; // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -65,7 +65,9 @@ describe(' getImpl()', () => { } // Call close() without await gitDDB.close().catch(() => {}); - await expect(getImpl(gitDDB, 'tmp', '')).rejects.toThrowError(Err.DatabaseClosingError); + await expect(getImpl(gitDDB, 'tmp', '', gitDDB.serializeFormat)).rejects.toThrowError( + Err.DatabaseClosingError + ); while (gitDDB.isClosing) { // eslint-disable-next-line no-await-in-loop await sleep(100); @@ -73,20 +75,6 @@ describe(' getImpl()', () => { await gitDDB.destroy(); }); - it('throws RepositoryNotOpenError', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - await gitDDB.close(); - await expect(getImpl(gitDDB, 'tmp', '')).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.destroy(); - }); - it('throws InvalidJsonObjectError', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -101,9 +89,9 @@ describe(' getImpl()', () => { const data = 'invalid data'; // JSON.parse() will throw error await addOneData(gitDDB, fullDocPath, data); - await expect(getImpl(gitDDB, shortName, collectionPath)).rejects.toThrowError( - Err.InvalidJsonObjectError - ); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).rejects.toThrowError(Err.InvalidJsonObjectError); await gitDDB.destroy(); }); @@ -117,12 +105,14 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); - await expect(getImpl(gitDDB, shortName, collectionPath)).resolves.toEqual(json); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toEqual(json); await gitDDB.destroy(); }); @@ -136,12 +126,14 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'dir01/prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); - await expect(getImpl(gitDDB, shortName, collectionPath)).resolves.toEqual(json); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toEqual(json); await gitDDB.destroy(); }); @@ -155,12 +147,14 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'dir01/prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = 'col01/col02/col03'; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); - await expect(getImpl(gitDDB, shortName, collectionPath)).resolves.toEqual(json); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toEqual(json); await gitDDB.destroy(); }); @@ -177,7 +171,9 @@ describe(' getImpl()', () => { const shortName = 'prof01.json'; const collectionPath = ''; - await expect(getImpl(gitDDB, shortName, collectionPath)).resolves.toBeUndefined(); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toBeUndefined(); await gitDDB.destroy(); }); @@ -193,7 +189,9 @@ describe(' getImpl()', () => { const shortName = 'dir01/prof01.json'; const collectionPath = ''; - await expect(getImpl(gitDDB, shortName, collectionPath)).resolves.toBeUndefined(); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toBeUndefined(); await gitDDB.destroy(); }); @@ -207,7 +205,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; @@ -216,7 +214,9 @@ describe(' getImpl()', () => { const stubReadBlob = sandbox.stub(git_module, 'readBlob'); stubReadBlob.rejects(); - await expect(getImpl(gitDDB, shortName, collectionPath)).resolves.toBeUndefined(); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toBeUndefined(); await gitDDB.destroy(); }); @@ -230,12 +230,14 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = '枕草子/春はあけぼの'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); - await expect(getImpl(gitDDB, shortName, collectionPath)).resolves.toEqual(json); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toEqual(json); await gitDDB.destroy(); }); @@ -250,14 +252,16 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; const { oid } = await git.hashBlob({ object: toSortedJSONString(json) }); await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { oid }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + oid, + }) ).resolves.toEqual(json); await gitDDB.destroy(); @@ -274,14 +278,16 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; const { oid } = await git.hashBlob({ object: toSortedJSONString(json) }); await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { withMetadata: true }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + withMetadata: true, + }) ).resolves.toEqual({ _id: shortId, name: shortName, @@ -302,14 +308,16 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: -1 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: -1, + }) ).resolves.toBeUndefined(); await gitDDB.destroy(); @@ -326,7 +334,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; @@ -334,7 +342,9 @@ describe(' getImpl()', () => { await removeOneData(gitDDB, fullDocPath); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 0 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 0, + }) ).resolves.toBeUndefined(); await gitDDB.destroy(); @@ -349,7 +359,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; @@ -357,7 +367,9 @@ describe(' getImpl()', () => { await removeOneData(gitDDB, fullDocPath); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 1 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 1, + }) ).resolves.toEqual(json); await gitDDB.destroy(); @@ -372,7 +384,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json01 = { _id: shortId, name: 'v01' }; @@ -382,7 +394,9 @@ describe(' getImpl()', () => { await removeOneData(gitDDB, fullDocPath); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 2 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 2, + }) ).resolves.toEqual(json01); await gitDDB.destroy(); @@ -397,7 +411,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json01 = { _id: shortId, name: 'v01' }; @@ -407,7 +421,9 @@ describe(' getImpl()', () => { await addOneData(gitDDB, fullDocPath, toSortedJSONString(json02)); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 2 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 2, + }) ).resolves.toEqual(json01); await gitDDB.destroy(); @@ -422,7 +438,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json01 = { _id: shortId, name: 'v01' }; @@ -432,7 +448,9 @@ describe(' getImpl()', () => { await addOneData(gitDDB, fullDocPath, toSortedJSONString(json02)); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 1 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 1, + }) ).resolves.toBeUndefined(); await gitDDB.destroy(); @@ -447,7 +465,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json01 = { _id: shortId, name: 'v01' }; @@ -457,7 +475,9 @@ describe(' getImpl()', () => { await addOneData(gitDDB, fullDocPath, toSortedJSONString(json02)); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 3 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 3, + }) ).resolves.toBeUndefined(); await gitDDB.destroy(); @@ -475,7 +495,9 @@ describe(' getImpl()', () => { const collectionPath = ''; await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 0 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 0, + }) ).resolves.toBeUndefined(); await gitDDB.destroy(); @@ -490,7 +512,7 @@ describe(' getImpl()', () => { await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + shortName; const json = { _id: shortId, name: 'Shirase' }; @@ -500,7 +522,9 @@ describe(' getImpl()', () => { stubReadBlob.rejects(); await expect( - getImpl(gitDDB, shortName, collectionPath, undefined, { revision: 0 }) + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat, undefined, { + revision: 0, + }) ).resolves.toBeUndefined(); await gitDDB.destroy(); @@ -515,7 +539,7 @@ describe(' getImpl()', () => { }); const targetId = '01'; - const targetName = targetId + JSON_EXT; + const targetName = targetId + JSON_POSTFIX; const collectionPath = ''; const fullDocPath = collectionPath + targetName; @@ -777,6 +801,7 @@ describe(' getImpl()', () => { gitDDB, targetName, collectionPath, + gitDDB.serializeFormat, undefined, { revision: 0 }, { @@ -795,6 +820,7 @@ describe(' getImpl()', () => { gitDDB, targetName, collectionPath, + gitDDB.serializeFormat, undefined, { revision: 1 }, { @@ -815,6 +841,7 @@ describe(' getImpl()', () => { gitDDB, targetName, collectionPath, + gitDDB.serializeFormat, undefined, { revision: 0 }, { @@ -831,6 +858,7 @@ describe(' getImpl()', () => { gitDDB, targetName, collectionPath, + gitDDB.serializeFormat, undefined, { revision: 1 }, { @@ -843,4 +871,28 @@ describe(' getImpl()', () => { ).resolves.toEqual(json14); }); }); + + describe('Front-Matter + Markdown', () => { + it('returns latest JsonDoc under deep collectionPath', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + + await gitDDB.open(); + const shortId = 'dir01/prof01'; + const shortName = shortId + FRONT_MATTER_POSTFIX; + const collectionPath = 'col01/col02/col03'; + const fullDocPath = collectionPath + shortName; + const json = { _id: shortId, name: 'Shirase', _body: 'Journey to the Antarctic' }; + await addOneData(gitDDB, fullDocPath, toFrontMatterMarkdown(json)); + await expect( + getImpl(gitDDB, shortName, collectionPath, gitDDB.serializeFormat) + ).resolves.toEqual(json); + + await gitDDB.destroy(); + }); + }); }); diff --git a/test/crud/history.test.ts b/test/crud/history.test.ts index 22129f04..9b416c28 100644 --- a/test/crud/history.test.ts +++ b/test/crud/history.test.ts @@ -23,7 +23,7 @@ import { GitDocumentDB } from '../../src/git_documentdb'; import { sleep, toSortedJSONString, utf8encode } from '../../src/utils'; import { getHistoryImpl, readOldBlob } from '../../src/crud/history'; -import { JSON_EXT } from '../../src/const'; +import { JSON_POSTFIX } from '../../src/const'; import { addOneData, removeOneData } from '../utils'; import { FatJsonDoc } from '../../src/types'; @@ -64,160 +64,6 @@ after(() => { fs.removeSync(path.resolve(localDir)); }); -// This test needs environment variables: -// - GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(' getHistoryImpl', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - it('gets all revisions sorted by date from merged commit', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours', - } - ); - - const _id = 'prof'; - const shortName = _id + JSON_EXT; - const jsonA1 = { _id, name: 'A-1' }; - const jsonA2 = { _id, name: 'A-2' }; - const jsonA3 = { _id, name: 'A-3' }; - const jsonB1 = { _id, name: 'B-1' }; - const jsonB2 = { _id, name: 'B-2' }; - const putResultA1 = await dbA.put(jsonA1); - await sleep(1500); - const putResultB1 = await dbB.put(jsonB1); - await sleep(1500); - const putResultA2 = await dbA.put(jsonA2); - await sleep(1500); - const putResultB2 = await dbB.put(jsonB2); - await sleep(1500); - const putResultA3 = await dbA.put(jsonA3); - await sleep(1500); - - await syncA.trySync(); - await syncB.trySync(); // Resolve conflict. jsonB2 wins. - - // Get - const history = await getHistoryImpl(dbB, shortName, '', undefined, undefined, true); - - expect(history[0]).toEqual({ - _id, - name: shortName, - fileOid: expect.stringMatching(/^[\da-z]{40}$/), - type: 'json', - doc: jsonB2, - }); - expect(history[1]).toEqual({ - _id, - name: shortName, - fileOid: expect.stringMatching(/^[\da-z]{40}$/), - type: 'json', - doc: jsonA3, - }); - expect(history[2]).toEqual({ - _id, - name: shortName, - fileOid: expect.stringMatching(/^[\da-z]{40}$/), - type: 'json', - doc: jsonB2, - }); - expect(history[3]).toEqual({ - _id, - name: shortName, - fileOid: expect.stringMatching(/^[\da-z]{40}$/), - type: 'json', - doc: jsonA2, - }); - expect(history[4]).toEqual({ - _id, - name: shortName, - fileOid: expect.stringMatching(/^[\da-z]{40}$/), - type: 'json', - doc: jsonB1, - }); - expect(history[5]).toEqual({ - _id, - name: shortName, - fileOid: expect.stringMatching(/^[\da-z]{40}$/), - type: 'json', - doc: jsonA1, - }); - - await destroyDBs([dbA, dbB]); - }); -}); - -maybe(' readOldBlob()', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - it('skips a merge commit', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours', - } - ); - dbA.author = { - name: 'authorA', - email: 'authorEmailA', - }; - dbB.author = { - name: 'authorB', - email: 'authorEmailB', - }; - - const jsonA1 = { _id: 'A1', name: 'A1' }; - const jsonA1internal = { _id: 'A1', name: 'A1' }; - const jsonB1 = { _id: 'B1', name: 'B1' }; - const putResultA1 = await dbA.put(jsonA1); - await sleep(1500); - await dbB.put(jsonB1); - await sleep(1500); - - await syncA.trySync(); - await syncB.trySync(); // dbB commits 'merge' - - await expect( - readOldBlob(dbB.workingDir, 'A1.json', 0, { filter: [{ author: dbB.author }] }) - ).resolves.toBeUndefined(); // merge commit is skipped, so jsonA1 does not exist. - - await expect( - readOldBlob(dbB.workingDir, 'A1.json', 0, { filter: [{ author: dbA.author }] }) - ).resolves.toEqual({ - oid: putResultA1.fileOid, - blob: utf8encode(toSortedJSONString(jsonA1internal)), - }); - - await destroyDBs([dbA, dbB]); - }); -}); - describe(' getHistoryImpl', () => { it('gets all revisions', async () => { const dbName = monoId(); @@ -228,7 +74,7 @@ describe(' getHistoryImpl', () => { await gitDDB.open(); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -236,7 +82,7 @@ describe(' getHistoryImpl', () => { await gitDDB.put(jsonA02); await gitDDB.put(jsonA03); const _idB = 'profB'; - const shortNameB = _idB + JSON_EXT; + const shortNameB = _idB + JSON_POSTFIX; const jsonB01 = { _id: _idB, name: 'v01' }; const jsonB02 = { _id: _idB, name: 'v02' }; await gitDDB.put(jsonB01); @@ -246,6 +92,8 @@ describe(' getHistoryImpl', () => { gitDDB, shortNameA, '', + gitDDB.serializeFormat, + undefined, undefined, true @@ -258,6 +106,7 @@ describe(' getHistoryImpl', () => { gitDDB, shortNameB, '', + gitDDB.serializeFormat, undefined, undefined, true @@ -278,7 +127,7 @@ describe(' getHistoryImpl', () => { await gitDDB.open(); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -293,7 +142,7 @@ describe(' getHistoryImpl', () => { await gitDDB.put(jsonA03); const _idB = 'profB'; - const shortNameB = _idB + JSON_EXT; + const shortNameB = _idB + JSON_POSTFIX; const jsonB01 = { _id: _idB, name: 'v01' }; const jsonB02 = { _id: _idB, name: 'v02' }; @@ -309,6 +158,7 @@ describe(' getHistoryImpl', () => { gitDDB, shortNameA, '', + gitDDB.serializeFormat, { filter: [{ author: { name: 'authorB', email: 'authorEmailB' } }], }, @@ -323,6 +173,7 @@ describe(' getHistoryImpl', () => { gitDDB, shortNameB, '', + gitDDB.serializeFormat, { filter: [{ author: { name: 'authorB', email: 'authorEmailB' } }], }, @@ -351,6 +202,7 @@ describe(' getHistoryImpl', () => { gitDDB, 'invalid_id', '', + gitDDB.serializeFormat, undefined, undefined, true @@ -369,7 +221,7 @@ describe(' getHistoryImpl', () => { await gitDDB.open(); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -385,6 +237,7 @@ describe(' getHistoryImpl', () => { gitDDB, shortNameA, '', + gitDDB.serializeFormat, undefined, undefined, true @@ -415,7 +268,15 @@ describe(' getHistoryImpl', () => { // Call close() without await gitDDB.close().catch(() => {}); await expect( - getHistoryImpl(gitDDB, '0.json', '', undefined, undefined, true) + getHistoryImpl( + gitDDB, + '0.json', + '', + gitDDB.serializeFormat, + undefined, + undefined, + true + ) ).rejects.toThrowError(Err.DatabaseClosingError); while (gitDDB.isClosing) { @@ -425,20 +286,6 @@ describe(' getHistoryImpl', () => { await destroyDBs([gitDDB]); }); - it('throws RepositoryNotOpenError', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - await gitDDB.close(); - await expect( - getHistoryImpl(gitDDB, 'tmp', '', undefined, undefined, true) - ).rejects.toThrowError(Err.RepositoryNotOpenError); - await destroyDBs([gitDDB]); - }); - it('throws InvalidJsonObjectError.', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -449,7 +296,15 @@ describe(' getHistoryImpl', () => { await gitDDB.putFatDoc('1.json', 'invalid json'); await expect( - getHistoryImpl(gitDDB, '1.json', '', undefined, undefined, true) + getHistoryImpl( + gitDDB, + '1.json', + '', + gitDDB.serializeFormat, + undefined, + undefined, + true + ) ).rejects.toThrowError(Err.InvalidJsonObjectError); await destroyDBs([gitDDB]); @@ -465,7 +320,7 @@ describe(' getHistoryImpl', () => { await gitDDB.open(); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -474,7 +329,7 @@ describe(' getHistoryImpl', () => { await gitDDB.put(jsonA03); // Get - const historyA = await getHistoryImpl(gitDDB, shortNameA, ''); + const historyA = await getHistoryImpl(gitDDB, shortNameA, '', gitDDB.serializeFormat); expect(historyA.length).toBe(3); expect(historyA[0]).toMatchObject(jsonA03); expect(historyA[1]).toMatchObject(jsonA02); @@ -492,7 +347,7 @@ describe(' getHistoryImpl', () => { await gitDDB.open(); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -508,6 +363,7 @@ describe(' getHistoryImpl', () => { gitDDB, shortNameA, '', + gitDDB.serializeFormat, undefined, undefined, false @@ -539,6 +395,7 @@ describe(' getHistoryImpl', () => { gitDDB, 'invalid_id', '', + gitDDB.serializeFormat, undefined, undefined, false @@ -561,7 +418,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); @@ -580,7 +437,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); await removeOneData(gitDDB, fullDocPath); @@ -600,7 +457,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); await removeOneData(gitDDB, fullDocPath); @@ -623,7 +480,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v01' }; const json02 = { _id: shortId, name: 'v02' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -648,7 +505,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v01' }; const json02 = { _id: shortId, name: 'v02' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -673,7 +530,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v01' }; const json02 = { _id: shortId, name: 'v02' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -695,7 +552,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v01' }; const json02 = { _id: shortId, name: 'v02' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -733,7 +590,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json = { _id: shortId, name: 'Shirase' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json)); @@ -755,7 +612,7 @@ describe(' readOldBlob()', () => { await gitDDB.open(); const shortId = 'prof01'; const collectionPath = ''; - const fullDocPath = collectionPath + shortId + JSON_EXT; + const fullDocPath = collectionPath + shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v01' }; const json02 = { _id: shortId, name: 'v02' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -780,7 +637,7 @@ describe(' readOldBlob()', () => { const targetId = '01'; const collectionPath = ''; - const fullDocPath = collectionPath + targetId + JSON_EXT; + const fullDocPath = collectionPath + targetId + JSON_POSTFIX; const json01 = { _id: targetId, name: 'v01' }; const json02 = { _id: targetId, name: 'v02' }; diff --git a/test/crud/put.test.ts b/test/crud/put.test.ts index 9fb14315..519fa8ca 100644 --- a/test/crud/put.test.ts +++ b/test/crud/put.test.ts @@ -17,7 +17,7 @@ import { monotonicFactory } from 'ulid'; import { Err } from '../../src/error'; import { GitDocumentDB } from '../../src/git_documentdb'; import { putImpl, putWorker } from '../../src/crud/put'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../../src/const'; +import { JSON_POSTFIX, SHORT_SHA_LENGTH } from '../../src/const'; import { sleep, toSortedJSONString } from '../../src/utils'; import { TaskMetadata } from '../../src/types'; @@ -37,6 +37,7 @@ beforeEach(function () { // @ts-ignore console.log(`... ${this.currentTest.fullTitle()}`); sandbox = sinon.createSandbox(); + fs.removeSync(path.resolve(localDir)); }); afterEach(function () { @@ -64,7 +65,13 @@ describe(' put', () => { gitDDB.close().catch(() => {}); const _id = 'prof01'; await expect( - putImpl(gitDDB, '', _id, _id + JSON_EXT, toSortedJSONString({ _id, name: 'shirase' })) + putImpl( + gitDDB, + '', + _id, + _id + JSON_POSTFIX, + toSortedJSONString({ _id, name: 'shirase' }) + ) ).rejects.toThrowError(Err.DatabaseClosingError); // wait close @@ -96,7 +103,7 @@ describe(' put', () => { gitDDB, '', _id, - _id + JSON_EXT, + _id + JSON_POSTFIX, toSortedJSONString(json) ); const afterTimestamp = Math.floor(Date.now() / 1000) * 1000; @@ -113,7 +120,7 @@ describe(' put', () => { // Check NormalizedCommit expect(pickedPutResult.commit.oid).toBe(currentCommitOid); expect(pickedPutResult.commit.message).toBe( - `insert: ${_id}${JSON_EXT}(${oid.substr(0, SHORT_SHA_LENGTH)})` + `insert: ${_id}${JSON_POSTFIX}(${oid.substr(0, SHORT_SHA_LENGTH)})` ); expect(pickedPutResult.commit.parent).toEqual([prevCommitOid]); expect(pickedPutResult.commit.author.name).toEqual(gitDDB.author.name); @@ -143,13 +150,13 @@ describe(' put', () => { gitDDB, '', _id, - _id + JSON_EXT, + _id + JSON_POSTFIX, toSortedJSONString(json) ); const shortOid = pickedPutResult.fileOid.substr(0, SHORT_SHA_LENGTH); expect(pickedPutResult.commit.message).toEqual( - `insert: ${_id}${JSON_EXT}(${shortOid})` + `insert: ${_id}${JSON_POSTFIX}(${shortOid})` ); // Check commit directly @@ -159,7 +166,7 @@ describe(' put', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`insert: ${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`insert: ${_id}${JSON_POSTFIX}(${shortOid})\n`); await gitDDB.destroy(); }); @@ -172,19 +179,19 @@ describe(' put', () => { await gitDDB.open(); const _id = 'prof01'; const json = { _id, name: 'Shirase' }; - await putImpl(gitDDB, '', _id, _id + JSON_EXT, toSortedJSONString(json)); + await putImpl(gitDDB, '', _id, _id + JSON_POSTFIX, toSortedJSONString(json)); // update const pickedPutResult = await putImpl( gitDDB, '', _id, - _id + JSON_EXT, + _id + JSON_POSTFIX, toSortedJSONString(json) ); const shortOid = pickedPutResult.fileOid.substr(0, SHORT_SHA_LENGTH); expect(pickedPutResult.commit.message).toEqual( - `update: ${_id}${JSON_EXT}(${shortOid})` + `update: ${_id}${JSON_POSTFIX}(${shortOid})` ); // Check commit directly @@ -194,7 +201,7 @@ describe(' put', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`update: ${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`update: ${_id}${JSON_POSTFIX}(${shortOid})\n`); await gitDDB.destroy(); }); @@ -211,11 +218,11 @@ describe(' put', () => { gitDDB, '', _id, - _id + JSON_EXT, + _id + JSON_POSTFIX, toSortedJSONString(json) ); const shortOid = pickedPutResult.fileOid.substr(0, SHORT_SHA_LENGTH); - const defaultCommitMessage = `insert: ${_id}${JSON_EXT}(${shortOid})`; + const defaultCommitMessage = `insert: ${_id}${JSON_POSTFIX}(${shortOid})`; expect(pickedPutResult.commit.message).toEqual(defaultCommitMessage); // Check commit directly @@ -245,7 +252,7 @@ describe(' put', () => { gitDDB, '', i.toString(), - i.toString() + JSON_EXT, + i.toString() + JSON_POSTFIX, toSortedJSONString({ _id: i.toString() }), { commitMessage: `${i}`, @@ -276,7 +283,7 @@ describe(' put', () => { gitDDB, '', _id, - _id + JSON_EXT, + _id + JSON_POSTFIX, toSortedJSONString(json), { commitMessage: myCommitMessage, @@ -325,54 +332,54 @@ describe(' put', () => { const json_p = { _id: _id_p, name: name_p }; await Promise.all([ - putImpl(gitDDB, '', _id_a, _id_a + JSON_EXT, toSortedJSONString(json_a)), - putImpl(gitDDB, '', _id_b, _id_b + JSON_EXT, toSortedJSONString(json_b)), - putImpl(gitDDB, '', _id_c01, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)), - putImpl(gitDDB, '', _id_c02, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)), - putImpl(gitDDB, '', _id_d, _id_d + JSON_EXT, toSortedJSONString(json_d)), - putImpl(gitDDB, '', _id_p, _id_p + JSON_EXT, toSortedJSONString(json_p)), + putImpl(gitDDB, '', _id_a, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)), + putImpl(gitDDB, '', _id_b, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)), + putImpl(gitDDB, '', _id_c01, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)), + putImpl(gitDDB, '', _id_c02, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)), + putImpl(gitDDB, '', _id_d, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)), + putImpl(gitDDB, '', _id_p, _id_p + JSON_POSTFIX, toSortedJSONString(json_p)), ]); await expect(gitDDB.findFatDoc()).resolves.toEqual( expect.arrayContaining([ { _id: _id_a, - name: _id_a + JSON_EXT, + name: _id_a + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_a) })).oid, type: 'json', doc: json_a, }, { _id: _id_b, - name: _id_b + JSON_EXT, + name: _id_b + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_b) })).oid, type: 'json', doc: json_b, }, { _id: _id_c01, - name: _id_c01 + JSON_EXT, + name: _id_c01 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c01) })).oid, type: 'json', doc: json_c01, }, { _id: _id_c02, - name: _id_c02 + JSON_EXT, + name: _id_c02 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c02) })).oid, type: 'json', doc: json_c02, }, { _id: _id_d, - name: _id_d + JSON_EXT, + name: _id_d + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_d) })).oid, type: 'json', doc: json_d, }, { _id: _id_p, - name: _id_p + JSON_EXT, + name: _id_p + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_p) })).oid, type: 'json', doc: json_p, @@ -398,7 +405,7 @@ describe(' put', () => { gitDDB, '', i.toString(), - i.toString() + JSON_EXT, + i.toString() + JSON_POSTFIX, toSortedJSONString({ _id: i.toString() }) ) ); @@ -427,12 +434,12 @@ describe(' put', () => { gitDDB, '', i.toString(), - i.toString() + JSON_EXT, + i.toString() + JSON_POSTFIX, toSortedJSONString({ _id: i.toString() }) ); } // The last put() with await keyword is resolved after all preceding (queued) Promises - await putImpl(gitDDB, '', '99', '99' + JSON_EXT, toSortedJSONString({ _id: '99' })); + await putImpl(gitDDB, '', '99', '99' + JSON_POSTFIX, toSortedJSONString({ _id: '99' })); const fatDocs = await gitDDB.find(); expect(fatDocs.length).toBe(100); @@ -449,13 +456,13 @@ describe(' put', () => { const enqueueEvent: TaskMetadata[] = []; const id1 = gitDDB.taskQueue.newTaskId(); const id2 = gitDDB.taskQueue.newTaskId(); - await putImpl(gitDDB, '', '1', '1' + JSON_EXT, toSortedJSONString({ _id: '1' }), { + await putImpl(gitDDB, '', '1', '1' + JSON_POSTFIX, toSortedJSONString({ _id: '1' }), { taskId: id1, enqueueCallback: (taskMetadata: TaskMetadata) => { enqueueEvent.push(taskMetadata); }, }); - await putImpl(gitDDB, '', '2', '2' + JSON_EXT, toSortedJSONString({ _id: '2' }), { + await putImpl(gitDDB, '', '2', '2' + JSON_POSTFIX, toSortedJSONString({ _id: '2' }), { taskId: id2, enqueueCallback: (taskMetadata: TaskMetadata) => { enqueueEvent.push(taskMetadata); @@ -483,7 +490,7 @@ describe(' put', () => { gitDDB, '', i.toString(), - i.toString() + JSON_EXT, + i.toString() + JSON_POSTFIX, toSortedJSONString({ _id: i.toString() }) ).catch( // eslint-disable-next-line no-loop-func @@ -492,37 +499,198 @@ describe(' put', () => { } ); } - gitDDB.taskQueue.clear(); + gitDDB.taskQueue.stop(); await sleep(3000); expect(taskCancelErrorCount).toBeGreaterThan(0); await gitDDB.destroy(); }); }); -describe(' putWorker', () => { - it('throws UndefinedDBError when Undefined DB', async () => { - // @ts-ignore - await expect(putWorker(undefined)).rejects.toThrowError(Err.UndefinedDBError); +describe(' put FatTextDoc', () => { + it('write text into .md without front-matter option', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const txt = 'Hello, world!'; + const fullDocPath = 'foo.md'; + await gitDDB.putFatDoc(fullDocPath, txt); + expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe(txt); + + await gitDDB.close(); + await gitDDB.destroy(); }); - it('throws RepositoryNotOpenError when a repository is not opened.', async () => { + it('write YAML into .yml without front-matter option', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ dbName, localDir, }); - await expect( - putWorker( - gitDDB, - '', - 'prof01' + JSON_EXT, - '{ "_id": "prof01", "name": "Shirase" }', - 'message' - ) - ).rejects.toThrowError(Err.RepositoryNotOpenError); + await gitDDB.open(); + const yaml = ` +_id: foo +a: aaa +b: bbb +`; + const fullDocPath = 'foo.yml'; + await gitDDB.putFatDoc(fullDocPath, yaml); + expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe(yaml); + + await gitDDB.close(); + await gitDDB.destroy(); + }); +}); + +describe(' put to front matter', () => { + it('write sorted front matter with markdown', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + await gitDDB.open(); + await gitDDB.put({ + b: 'bbb', + a: 'aaa', + _id: 'foo', + _body: 'This is a body text.\nThe second line.', + c: 'ccc', + array: [1, 2, 3], + }); + const result = `--- +_id: foo +a: aaa +array: + - 1 + - 2 + - 3 +b: bbb +c: ccc +--- +This is a body text. +The second line.`; + const fullDocPath = 'foo.md'; + expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe(result); + + await gitDDB.close(); + await gitDDB.destroy(); + }); + + it('write hierarchical front matter with markdown', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + await gitDDB.open(); + await gitDDB.put({ + a: { + a_1: 'a-1', + a_2: 'a-2', + }, + b: [{ b_1: 'b-1' }, { b_2: 'b-2' }], + _id: 'foo', + _body: 'This is a body text.\nThe second line.', + }); + const result = `--- +_id: foo +a: + a_1: a-1 + a_2: a-2 +b: + - b_1: b-1 + - b_2: b-2 +--- +This is a body text. +The second line.`; + const fullDocPath = 'foo.md'; + expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe(result); + + await gitDDB.close(); await gitDDB.destroy(); }); + it('write non-ASCII front matter with markdown', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + await gitDDB.open(); + await gitDDB.put({ + a: '春はあけぼの', + _id: 'foo', + _body: + 'やうやう白くなりゆく山ぎは、すこしあかりて、紫だちたる雲のほそくたなびきたる。', + }); + const result = `--- +_id: foo +a: 春はあけぼの +--- +やうやう白くなりゆく山ぎは、すこしあかりて、紫だちたる雲のほそくたなびきたる。`; + const fullDocPath = 'foo.md'; + expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe(result); + + await gitDDB.close(); + await gitDDB.destroy(); + }); + + it('write yaml when no markdown', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + await gitDDB.open(); + await gitDDB.put({ + _id: 'foo', + a: 'bar', + }); + const result = `_id: foo +a: bar +`; + const fullDocPath = 'foo.yml'; + expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe(result); + + await gitDDB.close(); + await gitDDB.destroy(); + }); + + it('write markdown without front matter', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + await gitDDB.open(); + await gitDDB.put({ + _id: 'foo', + _body: 'bar\nbaz', + }); + const result = `bar +baz`; + const fullDocPath = 'foo.md'; + expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe(result); + + await gitDDB.close(); + await gitDDB.destroy(); + }); +}); + +describe(' putWorker', () => { + it('throws UndefinedDBError when Undefined DB', async () => { + // @ts-ignore + await expect(putWorker(undefined)).rejects.toThrowError(Err.UndefinedDBError); + }); + it('throws CannotCreateDirectoryError', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -538,7 +706,7 @@ describe(' putWorker', () => { putWorker( gitDDB, '', - 'prof01' + JSON_EXT, + 'prof01' + JSON_POSTFIX, '{ "_id": "prof01", "name": "Shirase" }', 'message' ) @@ -553,7 +721,7 @@ describe(' putWorker', () => { localDir, }); await gitDDB.open(); - const fullDocPath = 'prof01' + JSON_EXT; + const fullDocPath = 'prof01' + JSON_POSTFIX; await putWorker( gitDDB, '', @@ -581,7 +749,7 @@ describe(' putWorker', () => { localDir, }); await gitDDB.open(); - const fullDocPath = 'prof01' + JSON_EXT; + const fullDocPath = 'prof01' + JSON_POSTFIX; await expect( putWorker( gitDDB, @@ -623,7 +791,7 @@ describe(' putWorker', () => { await gitDDB.open(); const json = { _id: 'prof01', name: 'Shirase' }; - const fullDocPath = json._id + JSON_EXT; + const fullDocPath = json._id + JSON_POSTFIX; await putWorker(gitDDB, '', fullDocPath, toSortedJSONString(json), 'message'); expect(readFileSync(path.resolve(gitDDB.workingDir, fullDocPath), 'utf8')).toBe( toSortedJSONString(json) @@ -641,7 +809,7 @@ describe(' putWorker', () => { await gitDDB.open(); const json = { _id: 'prof01', name: 'Shirase' }; - const fullDocPath = json._id + JSON_EXT; + const fullDocPath = json._id + JSON_POSTFIX; await putWorker(gitDDB, '', fullDocPath, toSortedJSONString(json), 'message'); const json2 = { _id: 'prof01', name: 'updated document' }; @@ -683,54 +851,66 @@ describe(' putWorker', () => { const json_p = { _id: _id_p, name: name_p }; await Promise.all([ - putWorker(gitDDB, '', _id_a + JSON_EXT, toSortedJSONString(json_a), 'message'), - putWorker(gitDDB, '', _id_b + JSON_EXT, toSortedJSONString(json_b), 'message'), - putWorker(gitDDB, '', _id_c01 + JSON_EXT, toSortedJSONString(json_c01), 'message'), - putWorker(gitDDB, '', _id_c02 + JSON_EXT, toSortedJSONString(json_c02), 'message'), - putWorker(gitDDB, '', _id_d + JSON_EXT, toSortedJSONString(json_d), 'message'), - putWorker(gitDDB, '', _id_p + JSON_EXT, toSortedJSONString(json_p), 'message'), + putWorker(gitDDB, '', _id_a + JSON_POSTFIX, toSortedJSONString(json_a), 'message'), + putWorker(gitDDB, '', _id_b + JSON_POSTFIX, toSortedJSONString(json_b), 'message'), + putWorker( + gitDDB, + '', + _id_c01 + JSON_POSTFIX, + toSortedJSONString(json_c01), + 'message' + ), + putWorker( + gitDDB, + '', + _id_c02 + JSON_POSTFIX, + toSortedJSONString(json_c02), + 'message' + ), + putWorker(gitDDB, '', _id_d + JSON_POSTFIX, toSortedJSONString(json_d), 'message'), + putWorker(gitDDB, '', _id_p + JSON_POSTFIX, toSortedJSONString(json_p), 'message'), ]); await expect(gitDDB.findFatDoc()).resolves.toEqual( expect.arrayContaining([ { _id: _id_a, - name: _id_a + JSON_EXT, + name: _id_a + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_a) })).oid, type: 'json', doc: json_a, }, { _id: _id_b, - name: _id_b + JSON_EXT, + name: _id_b + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_b) })).oid, type: 'json', doc: json_b, }, { _id: _id_c01, - name: _id_c01 + JSON_EXT, + name: _id_c01 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c01) })).oid, type: 'json', doc: json_c01, }, { _id: _id_c02, - name: _id_c02 + JSON_EXT, + name: _id_c02 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c02) })).oid, type: 'json', doc: json_c02, }, { _id: _id_d, - name: _id_d + JSON_EXT, + name: _id_d + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_d) })).oid, type: 'json', doc: json_d, }, { _id: _id_p, - name: _id_p + JSON_EXT, + name: _id_p + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_p) })).oid, type: 'json', doc: json_p, diff --git a/test/git_documentdb.test.ts b/test/git_documentdb.test.ts index 08ae24ea..157b8e26 100644 --- a/test/git_documentdb.test.ts +++ b/test/git_documentdb.test.ts @@ -183,24 +183,4 @@ describe('', () => { await gitDDB.destroy(); }); - - it('save and load AppInfo', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - - await gitDDB.open(); - - const json = { - appName: 'foo', - appVersion: 1, - }; - await gitDDB.saveAppInfo(json); - - await expect(gitDDB.loadAppInfo()).resolves.toEqual(json); - - await gitDDB.destroy(); - }); }); diff --git a/test/git_documentdb_crud.test.ts b/test/git_documentdb_crud.test.ts index cc6343ac..527512ad 100644 --- a/test/git_documentdb_crud.test.ts +++ b/test/git_documentdb_crud.test.ts @@ -14,8 +14,8 @@ import expect from 'expect'; import fs from 'fs-extra'; import { DeleteResultJsonDoc, PutResultJsonDoc } from '../src/types'; import { GitDocumentDB } from '../src/git_documentdb'; -import { sleep, toSortedJSONString } from '../src/utils'; -import { JSON_EXT, SHORT_SHA_LENGTH } from '../src/const'; +import { sleep, toFrontMatterMarkdown, toSortedJSONString } from '../src/utils'; +import { FRONT_MATTER_POSTFIX, JSON_POSTFIX, SHORT_SHA_LENGTH } from '../src/const'; import { addOneData } from './utils'; import { Err } from '../src/error'; @@ -85,16 +85,44 @@ describe(' put(jsonDoc)', () => { const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(json)); await gitDDB.destroy(); }); + it('creates a Front Matter + Markdown file', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); + await gitDDB.open(); + const _id = 'prof01'; + // Check put operation + const json = { _id, name: 'Shirase', _body: 'Journey to the Antarctic' }; + const putResult = await gitDDB.put(json); + const fileOid = (await git.hashBlob({ object: toFrontMatterMarkdown(json) })).oid; + const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); + expect(putResult._id).toBe(_id); + expect(putResult.fileOid).toBe(fileOid); + expect(putResult.commit.message).toBe( + `insert: ${_id}${FRONT_MATTER_POSTFIX}(${shortOid})` + ); + + // fs.access() throw error when a file cannot be accessed. + const filePath = path.resolve(gitDDB.workingDir, _id + FRONT_MATTER_POSTFIX); + await expect(fs.access(filePath)).resolves.not.toThrowError(); + expect(fs.readFileSync(filePath, 'utf8')).toBe(toFrontMatterMarkdown(json)); + + await gitDDB.destroy(); + }); + it('puts with a commitMessage', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -196,10 +224,10 @@ describe(' put(_id, jsonDoc)', () => { const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(json)); @@ -279,17 +307,17 @@ describe(' putFatDoc(name, jsonDoc)', () => { }); await gitDDB.open(); const _id = 'prof01'; - const name = _id + JSON_EXT; + const name = _id + JSON_POSTFIX; const json = { _id, name: 'Shirase' }; const putResult = (await gitDDB.putFatDoc(name, json)) as PutResultJsonDoc; const fileOid = (await git.hashBlob({ object: toSortedJSONString(json) })).oid; const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(json)); @@ -312,10 +340,10 @@ describe(' insert(jsonDoc)', () => { const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(json)); @@ -357,10 +385,10 @@ describe(' insert(_id, jsonDoc)', () => { const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(json)); @@ -396,17 +424,17 @@ describe(' insertFatDoc(name, jsonDoc)', () => { }); await gitDDB.open(); const _id = 'prof01'; - const name = _id + JSON_EXT; + const name = _id + JSON_POSTFIX; const json = { _id, name: 'Shirase' }; const putResult = (await gitDDB.insertFatDoc(name, json)) as PutResultJsonDoc; const fileOid = (await git.hashBlob({ object: toSortedJSONString(json) })).oid; const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`insert: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(json)); @@ -432,10 +460,10 @@ describe(' update(jsonDoc)', () => { const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`update: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`update: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(jsonUpdated)); @@ -480,10 +508,10 @@ describe(' update(_id, jsonDoc', () => { const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`update: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`update: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(jsonUpdated)); @@ -520,7 +548,7 @@ describe(' updateFatDoc(name, jsonDoc', () => { }); await gitDDB.open(); const _id = 'prof01'; - const name = _id + JSON_EXT; + const name = _id + JSON_POSTFIX; const json = { _id, name: 'Shirase' }; await gitDDB.insert(json); const jsonUpdated = { _id, name: 'updated' }; @@ -529,10 +557,10 @@ describe(' updateFatDoc(name, jsonDoc', () => { const shortOid = fileOid.substr(0, SHORT_SHA_LENGTH); expect(putResult._id).toBe(_id); expect(putResult.fileOid).toBe(fileOid); - expect(putResult.commit.message).toBe(`update: ${_id}${JSON_EXT}(${shortOid})`); + expect(putResult.commit.message).toBe(`update: ${_id}${JSON_POSTFIX}(${shortOid})`); // fs.access() throw error when a file cannot be accessed. - const filePath = path.resolve(gitDDB.workingDir, _id + JSON_EXT); + const filePath = path.resolve(gitDDB.workingDir, _id + JSON_POSTFIX); await expect(fs.access(filePath)).resolves.not.toThrowError(); expect(fs.readFileSync(filePath, 'utf8')).toBe(toSortedJSONString(jsonUpdated)); @@ -563,7 +591,7 @@ describe(' get()', () => { }); await gitDDB.open(); const shortId = 'dir01/prof01'; - const fullDocPath = shortId + JSON_EXT; + const fullDocPath = shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -579,7 +607,7 @@ describe(' get()', () => { }); await gitDDB.open(); const shortId = 'prof01'; - const fullDocPath = shortId + JSON_EXT; + const fullDocPath = shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -598,8 +626,8 @@ describe(' getFatDoc()', () => { }); await gitDDB.open(); const shortId = 'prof01'; - const shortName = shortId + JSON_EXT; - const fullDocPath = shortId + JSON_EXT; + const shortName = shortId + JSON_POSTFIX; + const fullDocPath = shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; const json02 = { _id: shortId, name: 'v2' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); @@ -627,6 +655,42 @@ describe(' getFatDoc()', () => { await expect(gitDDB.getFatDoc(shortId)).resolves.toBeUndefined(); await gitDDB.destroy(); }); + + it('get text from .md without front-matter option', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const txt = 'Hello, world!'; + const fullDocPath = 'foo.md'; + await gitDDB.putFatDoc(fullDocPath, txt); + const fatDoc = await gitDDB.getFatDoc(fullDocPath); + expect(fatDoc?.doc).toBe(txt); + await gitDDB.close(); + await gitDDB.destroy(); + }); + + it('get YAML from .yml without front-matter option', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const yaml = ` +_id: foo +a: aaa +b: bbb +`; + const fullDocPath = 'foo.yml'; + await gitDDB.putFatDoc(fullDocPath, yaml); + const fatDoc = await gitDDB.getFatDoc(fullDocPath); + expect(fatDoc?.doc).toBe(yaml); + await gitDDB.close(); + await gitDDB.destroy(); + }); }); describe(' getDocByOid()', () => { @@ -638,7 +702,7 @@ describe(' getDocByOid()', () => { }); await gitDDB.open(); const shortId = 'dir01/prof01'; - const fullDocPath = shortId + JSON_EXT; + const fullDocPath = shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); const { oid } = await git.hashBlob({ object: toSortedJSONString(json01) }); @@ -654,7 +718,7 @@ describe(' getDocByOid()', () => { }); await gitDDB.open(); const shortId = 'dir01/prof01'; - const fullDocPath = shortId + JSON_EXT; + const fullDocPath = shortId + JSON_POSTFIX; const json01 = { _id: shortId, name: 'v1' }; await addOneData(gitDDB, fullDocPath, toSortedJSONString(json01)); await expect(gitDDB.getDocByOid('not exist', 'json')).resolves.toBeUndefined(); @@ -670,8 +734,8 @@ describe('', () => { }); const targetId = '01'; - const targetName = targetId + JSON_EXT; - const fullDocPath = targetId + JSON_EXT; + const targetName = targetId + JSON_POSTFIX; + const fullDocPath = targetId + JSON_POSTFIX; const json01 = { _id: targetId, name: 'v01' }; const json02 = { _id: targetId, name: 'v02' }; @@ -1099,7 +1163,7 @@ describe(' getFatDocHistory()', () => { await gitDDB.open(); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -1107,7 +1171,7 @@ describe(' getFatDocHistory()', () => { await gitDDB.put(jsonA02); await gitDDB.put(jsonA03); const _idB = 'profB'; - const shortNameB = _idB + JSON_EXT; + const shortNameB = _idB + JSON_POSTFIX; const jsonB01 = { _id: _idB, name: 'v01' }; const jsonB02 = { _id: _idB, name: 'v02' }; await gitDDB.put(jsonB01); @@ -1135,7 +1199,7 @@ describe(' getFatDocHistory()', () => { await gitDDB.open(); const _idA = 'profA'; - const shortNameA = _idA + JSON_EXT; + const shortNameA = _idA + JSON_POSTFIX; const jsonA01 = { _id: _idA, name: 'v01' }; const jsonA02 = { _id: _idA, name: 'v02' }; const jsonA03 = { _id: _idA, name: 'v03' }; @@ -1150,7 +1214,7 @@ describe(' getFatDocHistory()', () => { await gitDDB.put(jsonA03); const _idB = 'profB'; - const shortNameB = _idB + JSON_EXT; + const shortNameB = _idB + JSON_POSTFIX; const jsonB01 = { _id: _idB, name: 'v01' }; const jsonB02 = { _id: _idB, name: 'v02' }; @@ -1221,20 +1285,6 @@ describe(' getFatDocHistory()', () => { await gitDDB.destroy(); }); - it('throws RepositoryNotOpenError', async () => { - const dbName = monoId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - await gitDDB.close(); - await expect(gitDDB.getFatDocHistory('tmp')).rejects.toThrowError( - Err.RepositoryNotOpenError - ); - await gitDDB.destroy(); - }); - it('throws InvalidJsonObjectError.', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -1391,7 +1441,7 @@ describe(' delete(_id)', () => { const deleteResult = await gitDDB.delete(_id); expect(deleteResult._id).toBe(_id); expect(deleteResult.fileOid).toBe(putResult.fileOid); - expect(deleteResult.commit.message).toBe(`delete: ${_id}${JSON_EXT}(${shortOid})`); + expect(deleteResult.commit.message).toBe(`delete: ${_id}${JSON_POSTFIX}(${shortOid})`); // Check commit directly const commitOid = await git.resolveRef({ fs, dir: gitDDB.workingDir, ref: 'HEAD' }); @@ -1400,7 +1450,7 @@ describe(' delete(_id)', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`delete: ${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`delete: ${_id}${JSON_POSTFIX}(${shortOid})\n`); await expect(gitDDB.delete(_id)).rejects.toThrowError(Err.DocumentNotFoundError); await expect(gitDDB.get(_id)).resolves.toBeUndefined(); @@ -1480,7 +1530,7 @@ describe(' delete(jsonDoc)', () => { // Check NormalizedCommit expect(deleteResult.commit.oid).toBe(currentCommitOid); expect(deleteResult.commit.message).toBe( - `delete: ${_id}${JSON_EXT}(${oid.substr(0, SHORT_SHA_LENGTH)})` + `delete: ${_id}${JSON_POSTFIX}(${oid.substr(0, SHORT_SHA_LENGTH)})` ); expect(deleteResult.commit.parent).toEqual([prevCommitOid]); expect(deleteResult.commit.author.name).toEqual(gitDDB.author.name); @@ -1506,9 +1556,9 @@ describe(' deleteFatDoc(name)', () => { await gitDDB.open(); const _id = 'test/prof01'; - const name = _id + JSON_EXT; + const name = _id + JSON_POSTFIX; const _id2 = 'test/prof02'; - const name2 = _id2 + JSON_EXT; + const name2 = _id2 + JSON_POSTFIX; const putResult = await gitDDB.put({ _id: _id, name: 'Shirase' }); await gitDDB.put({ _id: _id2, name: 'Soya' }); @@ -1518,7 +1568,7 @@ describe(' deleteFatDoc(name)', () => { const deleteResult = (await gitDDB.deleteFatDoc(name)) as DeleteResultJsonDoc; expect(deleteResult._id).toBe(_id); expect(deleteResult.fileOid).toBe(putResult.fileOid); - expect(deleteResult.commit.message).toBe(`delete: ${_id}${JSON_EXT}(${shortOid})`); + expect(deleteResult.commit.message).toBe(`delete: ${_id}${JSON_POSTFIX}(${shortOid})`); // Check commit directly const commitOid = await git.resolveRef({ fs, dir: gitDDB.workingDir, ref: 'HEAD' }); @@ -1527,7 +1577,7 @@ describe(' deleteFatDoc(name)', () => { dir: gitDDB.workingDir, oid: commitOid, }); - expect(commit.message).toEqual(`delete: ${_id}${JSON_EXT}(${shortOid})\n`); + expect(commit.message).toEqual(`delete: ${_id}${JSON_POSTFIX}(${shortOid})\n`); await expect(gitDDB.deleteFatDoc(name)).rejects.toThrowError(Err.DocumentNotFoundError); await expect(gitDDB.get(_id)).resolves.toBeUndefined(); @@ -1579,7 +1629,7 @@ describe('', () => { }); await gitDDB.open(); - await addOneData(gitDDB, 'invalidJSON' + JSON_EXT, 'invalidJSON'); + await addOneData(gitDDB, 'invalidJSON' + JSON_POSTFIX, 'invalidJSON'); await expect(gitDDB.find()).rejects.toThrowError(Err.InvalidJsonObjectError); @@ -1621,11 +1671,11 @@ describe('', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); await expect(gitDDB.find()).resolves.toEqual([ json_a_, @@ -1663,13 +1713,13 @@ describe('', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'citrus/'; @@ -1702,13 +1752,13 @@ describe('', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'cit'; @@ -1744,13 +1794,13 @@ describe('', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'citrus'; @@ -1788,13 +1838,13 @@ describe('', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'citrus/y'; @@ -1827,13 +1877,13 @@ describe('', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); const prefix = 'not_exist/'; @@ -1869,15 +1919,15 @@ describe('', () => { const json_c01_ = { _id: _id_c01, name: name_c01 }; const json_c02_ = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_p + JSON_EXT, toSortedJSONString(json_p)); + await addOneData(gitDDB, _id_p + JSON_POSTFIX, toSortedJSONString(json_p)); - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c000 + JSON_EXT, toSortedJSONString(json_c000)); - await addOneData(gitDDB, _id_c001 + JSON_EXT, toSortedJSONString(json_c001)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c000 + JSON_POSTFIX, toSortedJSONString(json_c000)); + await addOneData(gitDDB, _id_c001 + JSON_POSTFIX, toSortedJSONString(json_c001)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); await expect(gitDDB.find({ prefix: 'pear/Japan' })).resolves.toEqual([json_p_]); @@ -1903,44 +1953,44 @@ describe('', () => { const json_c01 = { _id: _id_c01, name: name_c01 }; const json_c02 = { _id: _id_c02, name: name_c02 }; - await addOneData(gitDDB, _id_b + JSON_EXT, toSortedJSONString(json_b)); - await addOneData(gitDDB, _id_a + JSON_EXT, toSortedJSONString(json_a)); - await addOneData(gitDDB, _id_d + JSON_EXT, toSortedJSONString(json_d)); - await addOneData(gitDDB, _id_c01 + JSON_EXT, toSortedJSONString(json_c01)); - await addOneData(gitDDB, _id_c02 + JSON_EXT, toSortedJSONString(json_c02)); + await addOneData(gitDDB, _id_b + JSON_POSTFIX, toSortedJSONString(json_b)); + await addOneData(gitDDB, _id_a + JSON_POSTFIX, toSortedJSONString(json_a)); + await addOneData(gitDDB, _id_d + JSON_POSTFIX, toSortedJSONString(json_d)); + await addOneData(gitDDB, _id_c01 + JSON_POSTFIX, toSortedJSONString(json_c01)); + await addOneData(gitDDB, _id_c02 + JSON_POSTFIX, toSortedJSONString(json_c02)); await expect(gitDDB.findFatDoc()).resolves.toEqual([ { _id: _id_a, - name: _id_a + JSON_EXT, + name: _id_a + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_a) })).oid, type: 'json', doc: json_a, }, { _id: _id_b, - name: _id_b + JSON_EXT, + name: _id_b + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_b) })).oid, type: 'json', doc: json_b, }, { _id: _id_c01, - name: _id_c01 + JSON_EXT, + name: _id_c01 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c01) })).oid, type: 'json', doc: json_c01, }, { _id: _id_c02, - name: _id_c02 + JSON_EXT, + name: _id_c02 + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_c02) })).oid, type: 'json', doc: json_c02, }, { _id: _id_d, - name: _id_d + JSON_EXT, + name: _id_d + JSON_POSTFIX, fileOid: (await git.hashBlob({ object: toSortedJSONString(json_d) })).oid, type: 'json', doc: json_d, diff --git a/test/git_documentdb_destroy.test.ts b/test/git_documentdb_destroy.test.ts index 7d1cab81..6041ccd2 100644 --- a/test/git_documentdb_destroy.test.ts +++ b/test/git_documentdb_destroy.test.ts @@ -34,7 +34,7 @@ after(() => { fs.removeSync(path.resolve(localDir)); }); -describe(' destroy()', () => { +describe(' destroy()', () => { it('closes and removes a database', async () => { const dbName = monoId(); diff --git a/test/git_documentdb_logger.test.ts b/test/git_documentdb_logger.test.ts new file mode 100644 index 00000000..61978e40 --- /dev/null +++ b/test/git_documentdb_logger.test.ts @@ -0,0 +1,80 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import expect from 'expect'; +import { monotonicFactory } from 'ulid'; +import { ILogObject } from 'tslog'; +import { Err } from '../src/error'; +import { GitDocumentDB } from '../src/git_documentdb'; + +const ulid = monotonicFactory(); +const monoId = () => { + return ulid(Date.now()); +}; + +const localDir = './test/database_logger'; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +describe(' logger', () => { + it('write log to a local file', async () => { + const dbName = monoId(); + const logPath = path.resolve(localDir + '/log.txt'); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + logLevel: 'debug', + logToTransport: (logObject: ILogObject) => { + fs.appendFileSync(logPath, logObject.argumentsArray[0] + '\n'); + }, + }); + await gitDDB.open(); + await gitDDB.put({ _id: 'test' }); + + const log = fs.readFileSync(logPath, 'utf-8'); + expect(log.startsWith('\u001b[43m\u001b[30mStart: put()')).toBeTruthy(); + fs.removeSync(logPath); + await gitDDB.destroy(); + }); + + it('write log to a local file without color style', async () => { + const dbName = monoId(); + const logPath = path.resolve(localDir + '/log.txt'); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + logLevel: 'debug', + logToTransport: (logObject: ILogObject) => { + fs.appendFileSync(logPath, logObject.argumentsArray[0] + '\n'); + }, + logColorEnabled: false, + }); + await gitDDB.open(); + await gitDDB.put({ _id: 'test' }); + + const log = fs.readFileSync(logPath, 'utf-8'); + expect(log.startsWith('Start: put()')).toBeTruthy(); + + fs.removeSync(logPath); + await gitDDB.destroy(); + }); +}); diff --git a/test/git_documentdb_open.test.ts b/test/git_documentdb_open.test.ts index a9b5ceda..f6cbd1c1 100644 --- a/test/git_documentdb_open.test.ts +++ b/test/git_documentdb_open.test.ts @@ -21,12 +21,14 @@ import { DATABASE_VERSION, FIRST_COMMIT_MESSAGE, GIT_DOCUMENTDB_INFO_ID, - JSON_EXT, + JSON_POSTFIX, } from '../src/const'; import { sleep } from '../src/utils'; // eslint-disable-next-line @typescript-eslint/no-var-requires const fs_module = require('fs-extra'); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const put_worker_module = require('../src/crud/put'); const ulid = monotonicFactory(); const monoId = () => { @@ -36,11 +38,11 @@ const monoId = () => { const localDir = `./test/database_open`; async function createDatabaseInfo (workingDir: string, info: string) { - const infoPath = path.resolve(workingDir, GIT_DOCUMENTDB_INFO_ID + JSON_EXT); + const infoPath = path.resolve(workingDir, GIT_DOCUMENTDB_INFO_ID + JSON_POSTFIX); await fs.ensureDir(path.dirname(infoPath)); await git.init({ fs, dir: workingDir, defaultBranch: 'main' }); await fs.writeFile(infoPath, info); - await git.add({ fs, dir: workingDir, filepath: GIT_DOCUMENTDB_INFO_ID + JSON_EXT }); + await git.add({ fs, dir: workingDir, filepath: GIT_DOCUMENTDB_INFO_ID + JSON_POSTFIX }); await git.commit({ fs, dir: workingDir, @@ -105,19 +107,41 @@ describe('', () => { }); // You don't have permission await expect(gitDDB.open()).rejects.toThrowError(Err.CannotCreateDirectoryError); + expect(stubEnsureDir.callCount).toBe(4); // try 1 + retry 3 }); - it('throws CannotCreateRepositoryError when tries to create a new repository on a readonly filesystem.', async () => { + it('succeeds after retry ensureDir in createRepository.', async () => { const dbName = monoId(); + const stubEnsureDir = sandbox.stub(fs_module, 'ensureDir'); - stubEnsureDir.onFirstCall().resolves().onSecondCall().rejects(); + stubEnsureDir.onCall(0).rejects(); + stubEnsureDir.onCall(1).rejects(); + stubEnsureDir.onCall(2).rejects(); + stubEnsureDir.onCall(3).callsFake(function (dir: string) { + return stubEnsureDir.wrappedMethod(dir); + }); + // for push_worker + stubEnsureDir.onCall(4).callsFake(function (dir: string) { + return stubEnsureDir.wrappedMethod(dir); + }); const gitDDB: GitDocumentDB = new GitDocumentDB({ dbName, localDir, }); + gitDDB.logLevel = 'trace'; // You don't have permission - await expect(gitDDB.open()).rejects.toThrowError(Err.CannotCreateRepositoryError); + await expect(gitDDB.open()).resolves.toMatchObject({ + // dbId: dbOpenResult.dbId, + creator: DATABASE_CREATOR, + version: DATABASE_VERSION, + isNew: true, + isCreatedByGitDDB: true, + isValidVersion: true, + }); + + expect(stubEnsureDir.callCount).toBe(5); // try 1 + retry 3 + push_worker 1 + await gitDDB.destroy(); }); it('creates a new repository.', async () => { @@ -137,6 +161,7 @@ describe('', () => { isNew: true, isCreatedByGitDDB: true, isValidVersion: true, + serialize: 'json', }); expect((dbOpenResult as DatabaseInfo).dbId).toMatch(/^[\dA-HJKMNP-TV-Z]{26}$/); @@ -169,6 +194,67 @@ describe('', () => { await gitDDB.destroy().catch(e => console.error(e)); fs.removeSync(path.resolve(defaultLocalDir)); }); + + it('succeeds after retry git.init in createRepository.', async () => { + const dbName = monoId(); + + const stubInit = sandbox.stub(git, 'init'); + stubInit.onCall(0).rejects(); + stubInit.onCall(1).rejects(); + stubInit.onCall(2).rejects(); + stubInit.onCall(3).callsFake(function (options: any) { + return stubInit.wrappedMethod(options); + }); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + gitDDB.logLevel = 'trace'; + // You don't have permission + await expect(gitDDB.open()).resolves.toMatchObject({ + // dbId: dbOpenResult.dbId, + creator: DATABASE_CREATOR, + version: DATABASE_VERSION, + isNew: true, + isCreatedByGitDDB: true, + isValidVersion: true, + }); + + expect(stubInit.callCount).toBe(4); // try 1 + retry 3 + await gitDDB.destroy(); + }); + + it('succeeds after retry putWorker in createRepository.', async () => { + const dbName = monoId(); + + const stubPut = sandbox.stub(put_worker_module, 'putWorker'); + stubPut.onCall(0).rejects(); + stubPut.onCall(1).rejects(); + stubPut.onCall(2).rejects(); + stubPut.onCall(3).callsFake(function (...options: any) { + return stubPut.wrappedMethod(...options); + }); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + gitDDB.logLevel = 'trace'; + // You don't have permission + await expect(gitDDB.open()).resolves.toMatchObject({ + // dbId: dbOpenResult.dbId, + creator: DATABASE_CREATOR, + version: DATABASE_VERSION, + isNew: true, + isCreatedByGitDDB: true, + isValidVersion: true, + }); + + expect(stubPut.callCount).toBe(4); // try 1 + retry 3 + + gitDDB.destroy(); + }); }); describe('open', () => { @@ -191,7 +277,7 @@ describe('', () => { }); // Create empty .git directory await fs.ensureDir(gitDDB.workingDir + '/.git/'); - await expect(gitDDB.open()).rejects.toThrowError(Err.CannotOpenRepositoryError); + await expect(gitDDB.open()).rejects.toThrowError(Err.CannotWriteDataError); }); it('opens an existing repository.', async () => { @@ -216,6 +302,7 @@ describe('', () => { isNew: false, isCreatedByGitDDB: true, isValidVersion: true, + serialize: 'json', }); expect(gitDDB.isOpened).toBeTruthy(); @@ -252,6 +339,7 @@ describe('', () => { isNew: false, isCreatedByGitDDB: false, isValidVersion: false, + serialize: 'json', }); await gitDDB.destroy(); }); @@ -282,6 +370,7 @@ describe('', () => { isNew: false, isCreatedByGitDDB: true, isValidVersion: false, + serialize: 'json', }); await gitDDB.destroy(); }); @@ -313,7 +402,10 @@ describe('', () => { isNew: false, isCreatedByGitDDB: true, isValidVersion: true, + serialize: 'json', }); + + await gitDDB.destroy(); }); it('opens db twice.', async () => { @@ -324,7 +416,26 @@ describe('', () => { }); // Create db - await gitDDB.open(); + const dbOpenResult = await gitDDB.open(); + const newDbId = (dbOpenResult as DatabaseInfo).dbId; + await expect(gitDDB.open()).resolves.toMatchObject({ + dbId: newDbId, + creator: DATABASE_CREATOR, + version: DATABASE_VERSION, + isNew: false, + isCreatedByGitDDB: true, + isValidVersion: true, + }); + await gitDDB.destroy(); + }); + + it('loads serializeFormat.', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + serialize: 'front-matter', + }); const dbOpenResult = await gitDDB.open(); const newDbId = (dbOpenResult as DatabaseInfo).dbId; @@ -335,6 +446,7 @@ describe('', () => { isNew: false, isCreatedByGitDDB: true, isValidVersion: true, + serialize: 'front-matter', }); await gitDDB.destroy(); }); diff --git a/test/internal_plugin/checkfetch.test.ts b/test/internal_plugin/checkfetch.test.ts new file mode 100644 index 00000000..66a5d9ac --- /dev/null +++ b/test/internal_plugin/checkfetch.test.ts @@ -0,0 +1,532 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import expect from 'expect'; +import git from 'isomorphic-git'; +import { + HTTPError401AuthorizationRequired, + HTTPError404NotFound, + InvalidAuthenticationTypeError, + InvalidGitRemoteError, + InvalidRepositoryURLError, + InvalidURLFormatError, + NetworkError, +} from 'git-documentdb-remote-errors'; +import sinon from 'sinon'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { checkFetch } from '../../src/plugin/remote-isomorphic-git'; +import { + createGitRemote, + createRemoteRepository, + destroyDBs, + destroyRemoteRepository, + removeRemoteRepositories, +} from '../remote_utils'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { Sync } from '../../src/remote/sync'; + +const reposPrefix = 'test_remote_isomorphic_git_check_fetch___'; +const localDir = `./test/database_check_fetch`; + +let idCounter = 0; +const serialId = () => { + return `${reposPrefix}${idCounter++}`; +}; + +// Use sandbox to restore stub and spy in parallel mocha tests +let sandbox: sinon.SinonSandbox; +beforeEach(function () { + sandbox = sinon.createSandbox(); + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +afterEach(function () { + sandbox.restore(); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +/** + * Prerequisites + * + * Environment variables: + * GITDDB_GITHUB_USER_URL: URL of your GitHub account + * e.g.) https://github.com/foo/ + * GITDDB_PERSONAL_ACCESS_TOKEN: The personal access token of your GitHub account + * GitHub repositories: + * remoteURLBase + 'test-private.git' must be a private repository. + */ +const userHome = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'] ?? ''; + +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +maybe(' checkFetch', () => { + const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + + before(async () => { + // Remove remote + await removeRemoteRepositories(reposPrefix); + }); + + describe('returns true', () => { + it('when connect to public repository with no personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { type: 'github' } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + const res = await checkFetch(dbA.workingDir, remoteOptions, sync.remoteName).catch( + error => error + ); + expect(res).not.toBeInstanceOf(Error); + + await destroyDBs([dbA]); + }); + + it('when connect to public repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + const res = await checkFetch(dbA.workingDir, remoteOptions, sync.remoteName).catch( + error => error + ); + expect(res).not.toBeInstanceOf(Error); + + await destroyDBs([dbA]); + }); + + it('when connect to private repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + const res = await checkFetch(dbA.workingDir, remoteOptions, sync.remoteName).catch( + error => error + ); + + expect(res).not.toBeInstanceOf(Error); + + await destroyDBs([dbA]); + }); + + it('after retries', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const stubRemote = sandbox.stub(git, 'getRemoteInfo2'); + stubRemote.onCall(0).rejects(new Error('connect EACCES')); + stubRemote.onCall(1).rejects(new Error('connect EACCES')); + stubRemote.onCall(2).rejects(new Error('connect EACCES')); + stubRemote.onCall(3).resolves(undefined); + + const res = await checkFetch(dbA.workingDir, remoteOptions, sync.remoteName).catch( + error => error + ); + expect(res).not.toBeInstanceOf(Error); + + expect(stubRemote.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + + it('when fetch from multiple Sync instances', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const res = await checkFetch(dbA.workingDir, remoteOptions, sync.remoteName).catch( + error => error + ); + expect(res).not.toBeInstanceOf(Error); + + const remoteUrl2 = remoteURLBase + 'test-public2.git'; + await destroyRemoteRepository(remoteUrl2); + await createRemoteRepository(remoteUrl2); + const remoteOptions2 = { + remoteUrl: remoteUrl2, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync2 = new Sync(dbA, remoteOptions2); + await createGitRemote(dbA.workingDir, remoteUrl2, sync2.remoteName); + + const res2 = await checkFetch(dbA.workingDir, remoteOptions2, sync2.remoteName).catch( + error => error + ); + expect(res2).not.toBeInstanceOf(Error); + + await destroyDBs([dbA]); + }); + }); + + it('throws NetworkError after retries', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const stubRemote = sandbox.stub(git, 'getRemoteInfo2'); + stubRemote.rejects(new Error('connect EACCES')); + + const res = await checkFetch(dbA.workingDir, remoteOptions, sync.remoteName).catch( + error => error + ); + expect(res).toBeInstanceOf(NetworkError); + + expect(stubRemote.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + + it('throws InvalidGitRemoteError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + const remoteUrl = 'foo-bar'; + + const err = await checkFetch(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(InvalidGitRemoteError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormat by checkFetch when http protocol is missing', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + const remoteUrl = 'foo-bar'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { remoteUrl }).catch(error => error); + + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: UrlParseError:/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by checkFetch when URL is malformed', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + const remoteUrl = 'https://foo.example.com:xxxx'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by checkFetch when HTTP host is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://foo.bar.example.com/gitddb-plugin/sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + describe('throws NetworkError', () => { + it('when IP address is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://127.0.0.1/gitddb-plugin/sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { + remoteUrl, + connection: { + type: 'github', + }, + }).catch(error => error); + expect(err).toBeInstanceOf(NetworkError); + expect(err.message).toMatch(/^Network error: Error: connect ECONNREFUSED/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError401AuthorizationRequired', () => { + it('when personal access token does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when connection setting not found', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { remoteUrl }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when invalid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: 'foo-bar' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError404NotFound', () => { + it('when valid auth and repository does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(HTTPError404NotFound); + expect(err.message).toMatch(/^HTTP Error: 404 Not Found/); + + await destroyDBs([dbA]); + }); + }); + + it('throws InvalidURLFormatError by createCredentialForGitHub', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + const remoteUrl = 'foo-bar'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await checkFetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch( + /^URL format is invalid: http protocol required in createCredentialForGitHub/ + ); + + await destroyDBs([dbA]); + }); + + it('throws InvalidRepositoryURLError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'foo/bar/test.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + await expect( + checkFetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }) + ).rejects.toThrowError(InvalidRepositoryURLError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + await expect( + // @ts-ignore + checkFetch(dbA.workingDir, { remoteUrl, connection: { type: 'foo' } }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError with SSH', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'git@foo.example.com:bar/sync-test.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + await expect( + checkFetch(dbA.workingDir, { + remoteUrl, + connection: { + type: 'ssh', + publicKeyPath: path.resolve(userHome, '.ssh/invalid-test.pub'), + privateKeyPath: path.resolve(userHome, '.ssh/invalid-test'), + passPhrase: '', + }, + }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + describe('throws CannotConnectError', () => { + // NetworkError is thrown when network is not connected. + // CannotConnectError will be thrown when other unexpected cases. + }); +}); diff --git a/test/internal_plugin/clone.test.ts b/test/internal_plugin/clone.test.ts new file mode 100644 index 00000000..226434b0 --- /dev/null +++ b/test/internal_plugin/clone.test.ts @@ -0,0 +1,448 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import expect from 'expect'; +import { + HTTPError401AuthorizationRequired, + HTTPError404NotFound, + InvalidAuthenticationTypeError, + InvalidRepositoryURLError, + InvalidSSHKeyPathError, + InvalidURLFormatError, + NetworkError, +} from 'git-documentdb-remote-errors'; +import git from 'isomorphic-git'; +import sinon from 'sinon'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { clone } from '../../src/plugin/remote-isomorphic-git'; +import { destroyDBs, removeRemoteRepositories } from '../remote_utils'; + +const reposPrefix = 'test_remote_isomorphic_git_clone___'; +const localDir = `./test/database_clone`; + +let idCounter = 0; +const serialId = () => { + return `${reposPrefix}${idCounter++}`; +}; + +// Use sandbox to restore stub and spy in parallel mocha tests +let sandbox: sinon.SinonSandbox; +beforeEach(function () { + sandbox = sinon.createSandbox(); + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +afterEach(function () { + sandbox.restore(); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +/** + * Prerequisites + * + * Environment variables: + * GITDDB_GITHUB_USER_URL: URL of your GitHub account + * e.g.) https://github.com/foo/ + * GITDDB_PERSONAL_ACCESS_TOKEN: The personal access token of your GitHub account + * GitHub repositories: + * remoteURLBase + 'test-private.git' must be a private repository. + */ +const userHome = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'] ?? ''; + +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +maybe(' clone', () => { + const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + + before(async () => { + // Remove remote + await removeRemoteRepositories(reposPrefix); + }); + + describe('succeeds', () => { + it('when connect to public repository with no personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-public.git'; + fs.ensureDirSync(dbA.workingDir); + const res = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github' }, + }).catch(error => error); + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('when connect to public repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-public.git'; + fs.ensureDirSync(dbA.workingDir); + const res = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('when connect to private repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-private.git'; + fs.ensureDirSync(dbA.workingDir); + const res = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('set default and another remote name', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-public.git'; + fs.ensureDirSync(dbA.workingDir); + const res = await clone( + dbA.workingDir, + { + remoteUrl, + connection: { type: 'github' }, + }, + 'another' + ).catch(error => error); + expect(res).toBeUndefined(); + + const urlDefault = await git.getConfig({ + fs, + dir: dbA.workingDir, + path: 'remote.origin.url', + }); + expect(urlDefault).toBe(remoteUrl); + + const fetchDefault = await git.getConfig({ + fs, + dir: dbA.workingDir, + path: 'remote.origin.fetch', + }); + expect(fetchDefault).toBe(`+refs/heads/*:refs/remotes/origin/*`); + + const url = await git.getConfig({ + fs, + dir: dbA.workingDir, + path: 'remote.another.url', + }); + expect(url).toBe(remoteUrl); + + const fetch = await git.getConfig({ + fs, + dir: dbA.workingDir, + path: 'remote.another.fetch', + }); + expect(fetch).toBe(`+refs/heads/*:refs/remotes/another/*`); + + await destroyDBs([dbA]); + }); + + it('after retries', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-public.git'; + fs.ensureDirSync(dbA.workingDir); + + const cloneStub = sandbox.stub(git, 'clone'); + cloneStub.onCall(0).rejects(new Error('connect EACCES')); + cloneStub.onCall(1).rejects(new Error('connect EACCES')); + cloneStub.onCall(2).rejects(new Error('connect EACCES')); + cloneStub.onCall(3).resolves(undefined); + + // Skip addRemote because repository is empty + const remoteStub = sandbox.stub(git, 'addRemote'); + remoteStub.resolves(); + + const res = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github' }, + }).catch(error => error); + expect(res).toBeUndefined(); + + expect(cloneStub.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + }); + + it('throws NetworkError after retries', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-public.git'; + fs.ensureDirSync(dbA.workingDir); + + const cloneStub = sandbox.stub(git, 'clone'); + cloneStub.rejects(new Error('connect EACCES')); + + const res = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github' }, + }).catch(error => error); + expect(res).toBeInstanceOf(NetworkError); + + expect(cloneStub.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormat by clone when http protocol is missing', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = 'foo-bar'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { remoteUrl }).catch(error => error); + await dbA.open(); + + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: UrlParseError:/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by clone when URL is malformed', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = 'https://foo.example.com:xxxx'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by checkFetch when HTTP host is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = 'https://foo.bar.example.com/gitddb-plugin/sync-test-invalid.git'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + describe('throws NetworkError', () => { + it('when IP address is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = 'https://127.0.0.1/gitddb-plugin/sync-test-invalid.git'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(NetworkError); + expect(err.message).toMatch(/^Network error: Error: connect ECONNREFUSED/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError401AuthorizationRequired', () => { + it('when personal access token does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-private.git'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when connection setting not found', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-private.git'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when invalid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-private.git'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: 'foo-bar' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError404NotFound', () => { + it('when valid auth and repository does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'sync-test-invalid.git'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(HTTPError404NotFound); + expect(err.message).toMatch(/^HTTP Error: 404 Not Found/); + + await destroyDBs([dbA]); + }); + }); + + describe.skip('throws CannotFetchError', () => { + // Other cases + }); + + it('throws InvalidURLFormatError by createCredentialForGitHub', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = 'foo-bar'; + fs.ensureDirSync(dbA.workingDir); + const err = await clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch( + /^URL format is invalid: http protocol required in createCredentialForGitHub/ + ); + + await destroyDBs([dbA]); + }); + + it('throws InvalidRepositoryURLError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'foo/bar/test.git'; + fs.ensureDirSync(dbA.workingDir); + await expect( + clone(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }) + ).rejects.toThrowError(InvalidRepositoryURLError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-private.git'; + fs.ensureDirSync(dbA.workingDir); + await expect( + // @ts-ignore + clone(dbA.workingDir, { remoteUrl, connection: { type: 'foo' } }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError with SSH', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'git@foo.example.com:bar/sync-test.git'; + fs.ensureDirSync(dbA.workingDir); + await expect( + // @ts-ignore + clone(dbA.workingDir, { + remoteUrl, + connection: { + type: 'ssh', + publicKeyPath: path.resolve(userHome, '.ssh/invalid-test.pub'), + privateKeyPath: path.resolve(userHome, '.ssh/invalid-test'), + passPhrase: '', + }, + }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + describe('throws CannotConnectError', () => { + // NetworkError is thrown when network is not connected. + // CannotConnectError will be thrown when other unexpected cases. + }); +}); diff --git a/test/internal_plugin/fetch.test.ts b/test/internal_plugin/fetch.test.ts new file mode 100644 index 00000000..4217ffcb --- /dev/null +++ b/test/internal_plugin/fetch.test.ts @@ -0,0 +1,636 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import expect from 'expect'; +import git from 'isomorphic-git'; +import { + HTTPError401AuthorizationRequired, + HTTPError404NotFound, + InvalidAuthenticationTypeError, + InvalidGitRemoteError, + InvalidRepositoryURLError, + InvalidURLFormatError, + NetworkError, +} from 'git-documentdb-remote-errors'; +import sinon from 'sinon'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { fetch } from '../../src/plugin/remote-isomorphic-git'; +import { + createGitRemote, + createRemoteRepository, + destroyDBs, + destroyRemoteRepository, + removeRemoteRepositories, +} from '../remote_utils'; +import { Sync } from '../../src/remote/sync'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_remote_isomorphic_git_fetch___'; +const localDir = `./test/database_fetch`; + +let idCounter = 0; +const serialId = () => { + return `${reposPrefix}${idCounter++}`; +}; + +// Use sandbox to restore stub and spy in parallel mocha tests +let sandbox: sinon.SinonSandbox; +beforeEach(function () { + sandbox = sinon.createSandbox(); + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +afterEach(function () { + sandbox.restore(); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +/** + * Prerequisites + * + * Environment variables: + * GITDDB_GITHUB_USER_URL: URL of your GitHub account + * e.g.) https://github.com/foo/ + * GITDDB_PERSONAL_ACCESS_TOKEN: The personal access token of your GitHub account + * GitHub repositories: + * remoteURLBase + 'test-private.git' must be a private repository. + * remoteURLBase + 'test-public.git' must be a public repository. + * remoteURLBase + 'test-public2.git' must be a public repository. + */ +const userHome = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'] ?? ''; + +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +maybe(' fetch', () => { + const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + + before(async () => { + // Remove remote + await removeRemoteRepositories(reposPrefix).catch(err => console.log(err)); + }); + + describe('succeeds', () => { + it('when connect to public repository with no personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { type: 'github' } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const res = await fetch( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('when connect to public repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const res = await fetch( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('when connect to private repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const res = await fetch( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('after retrying push()', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const stubFetch = sandbox.stub(git, 'fetch'); + stubFetch.onCall(0).rejects(new Error('connect EACCES')); + stubFetch.onCall(1).rejects(new Error('connect EACCES')); + stubFetch.onCall(2).rejects(new Error('connect EACCES')); + stubFetch.onCall(3).resolves(undefined); + + const res = await fetch( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeUndefined(); + + expect(stubFetch.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + + it('when fetch from empty repository', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + serialId(); + await destroyRemoteRepository(remoteUrl).catch(() => {}); + await createRemoteRepository(remoteUrl); + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const res = await fetch( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('when fetch from multiple Sync instances', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const res = await fetch( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + expect(res).toBeUndefined(); + + const remoteUrl2 = remoteURLBase + 'test-public2.git'; + await destroyRemoteRepository(remoteUrl2); + await createRemoteRepository(remoteUrl2); + const remoteOptions2 = { + remoteUrl: remoteUrl2, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync2 = new Sync(dbA, remoteOptions2); + await createGitRemote(dbA.workingDir, remoteUrl2, sync2.remoteName); + + const res2 = await fetch( + dbA.workingDir, + remoteOptions2, + sync2.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + expect(res2).toBeUndefined(); + + await destroyDBs([dbA]); + }); + }); + + it('throws NetworkError after retrying push()', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const stubFetch = sandbox.stub(git, 'fetch'); + stubFetch.rejects(new Error('connect EACCES')); + + const res = await fetch( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeInstanceOf(NetworkError); + + expect(stubFetch.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + + it('throws InvalidGitRemoteError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'foo-bar'; + const err = await fetch(dbA.workingDir, { remoteUrl }).catch(error => error); + + expect(err).toBeInstanceOf(InvalidGitRemoteError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidGitRemoteError by NoRefspecError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const stubPush = sandbox.stub(git, 'fetch'); + stubPush.rejects(new Error('NoRefspecError')); + + const remoteUrl = 'foo-bar'; + const err = await fetch(dbA.workingDir, { remoteUrl }).catch(error => error); + + expect(err).toBeInstanceOf(InvalidGitRemoteError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormat by fetch when http protocol is missing', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'foo-bar'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { remoteUrl }).catch(error => error); + + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: UrlParseError:/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by fetch when URL is malformed', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://foo.example.com:xxxx'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by checkFetch when HTTP host is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://foo.bar.example.com/gitddb-plugin/sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + const err = await fetch(dbA.workingDir, { remoteUrl }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + describe('throws NetworkError', () => { + it('when IP address is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://127.0.0.1/gitddb-plugin/sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { + remoteUrl, + connection: { + type: 'github', + }, + }).catch(error => error); + + expect(err).toBeInstanceOf(NetworkError); + expect(err.message).toMatch(/^Network error: Error: connect ECONNREFUSED/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError401AuthorizationRequired', () => { + it('when personal access token does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when connection setting not found', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { remoteUrl }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when invalid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: 'foo-bar' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError404NotFound', () => { + it('when valid auth and repository does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(HTTPError404NotFound); + expect(err.message).toMatch(/^HTTP Error: 404 Not Found/); + + await destroyDBs([dbA]); + }); + }); + + it('throws InvalidURLFormatError by createCredentialForGitHub', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'foo-bar'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await fetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch( + /^URL format is invalid: http protocol required in createCredentialForGitHub/ + ); + + await destroyDBs([dbA]); + }); + + it('throws InvalidRepositoryURLError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'foo/bar/test.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + await expect( + fetch(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }) + ).rejects.toThrowError(InvalidRepositoryURLError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + await expect( + // @ts-ignore + fetch(dbA.workingDir, { remoteUrl, connection: { type: 'foo' } }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError with SSH', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + await expect( + // @ts-ignore + fetch(dbA.workingDir, { + remoteUrl, + connection: { + type: 'ssh', + publicKeyPath: path.resolve(userHome, '.ssh/invalid-test.pub'), + privateKeyPath: path.resolve(userHome, '.ssh/invalid-test'), + passPhrase: '', + }, + }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + describe('throws CannotConnectError', () => { + // NetworkError is thrown when network is not connected. + // CannotConnectError will be thrown when other unexpected cases. + }); +}); diff --git a/test/internal_plugin/push.test.ts b/test/internal_plugin/push.test.ts new file mode 100644 index 00000000..09692231 --- /dev/null +++ b/test/internal_plugin/push.test.ts @@ -0,0 +1,669 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import git from 'isomorphic-git'; +import fs from 'fs-extra'; +import expect from 'expect'; +import { + CannotConnectError, + HTTPError401AuthorizationRequired, + HTTPError403Forbidden, + HTTPError404NotFound, + InvalidAuthenticationTypeError, + InvalidGitRemoteError, + InvalidRepositoryURLError, + InvalidURLFormatError, + NetworkError, + UnfetchedCommitExistsError, +} from 'git-documentdb-remote-errors'; +import sinon from 'sinon'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { ConnectionSettingsGitHub, RemoteOptions } from '../../src/types'; +import { clone, push } from '../../src/plugin/remote-isomorphic-git'; +import { + createClonedDatabases, + createGitRemote, + createRemoteRepository, + destroyDBs, + removeRemoteRepositories, +} from '../remote_utils'; +import { Sync } from '../../src/remote/sync'; + +const reposPrefix = 'test_remote_isomorphic_git_push___'; +const localDir = `./test/database_push`; + +let idCounter = 0; +const serialId = () => { + return `${reposPrefix}${idCounter++}`; +}; + +// Use sandbox to restore stub and spy in parallel mocha tests +let sandbox: sinon.SinonSandbox; +beforeEach(function () { + sandbox = sinon.createSandbox(); + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +afterEach(function () { + sandbox.restore(); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + // fs.removeSync(path.resolve(localDir)); +}); + +/** + * Prerequisites + * + * Environment variables: + * GITDDB_GITHUB_USER_URL: URL of your GitHub account + * e.g.) https://github.com/foo/ + * GITDDB_PERSONAL_ACCESS_TOKEN: The personal access token of your GitHub account + * GitHub repositories: + * remoteURLBase + 'test-private.git' must be a private repository. + */ +const userHome = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'] ?? ''; + +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +maybe(' push', () => { + const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + + before(async () => { + // Remove remote + await removeRemoteRepositories(reposPrefix).catch(err => console.log(err)); + }); + + it('throws InvalidGitRemoteError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'foo-bar'; + + const err = await push(dbA.workingDir, { remoteUrl }, undefined, undefined).catch( + error => error + ); + + expect(err).toBeInstanceOf(InvalidGitRemoteError); + + await destroyDBs([dbA]); + }); + + describe('succeeds', () => { + it('when connect to empty repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + serialId(); + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + + await dbA.open(); + await dbA.put({ name: 'fromA' }); + + await createRemoteRepository(remoteUrl); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + const res = await push( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('when connect to cloned repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + 'test-public.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + fs.ensureDirSync(dbA.workingDir); + await clone(dbA.workingDir, remoteOptions, sync.remoteName); + await dbA.open(); + await dbA.put({ name: 'fromA' }); + // await createGitRemote(dbA.workingDir, remoteUrl); // Not need because cloned repository. + + const res = await push( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('when connect to private repository with valid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + + const remoteUrl = remoteURLBase + 'test-private.git'; + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + fs.ensureDirSync(dbA.workingDir); + await clone(dbA.workingDir, remoteOptions); + await dbA.open(); + await dbA.put({ name: 'fromA' }); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const res = await push( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeUndefined(); + + await destroyDBs([dbA]); + }); + + it('after retrying push()', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + serialId(); + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await dbA.open(); + await dbA.put({ name: 'fromA' }); + await createRemoteRepository(remoteUrl); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const stubPush = sandbox.stub(git, 'push'); + stubPush.onCall(0).rejects(new Error('connect EACCES')); + stubPush.onCall(1).rejects(new Error('connect EACCES')); + stubPush.onCall(2).rejects(new Error('connect EACCES')); + stubPush.onCall(3).resolves(undefined); + + const res = await push( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeUndefined(); + + expect(stubPush.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + }); + + it('throws NetworkError after retrying push()', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + const remoteUrl = remoteURLBase + serialId(); + const remoteOptions = { + remoteUrl, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + connection: { + type: 'github', + personalAccessToken: token, + } as ConnectionSettingsGitHub, + }; + const sync = new Sync(dbA, remoteOptions); + await dbA.open(); + await dbA.put({ name: 'fromA' }); + await createRemoteRepository(remoteUrl); + await createGitRemote(dbA.workingDir, remoteUrl, sync.remoteName); + + const stubPush = sandbox.stub(git, 'push'); + stubPush.rejects(new Error('connect EACCES')); + + const res = await push( + dbA.workingDir, + remoteOptions, + sync.remoteName, + dbA.defaultBranch, + dbA.defaultBranch + ).catch(error => error); + + expect(res).toBeInstanceOf(NetworkError); + + expect(stubPush.callCount).toBe(4); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormat by push when http protocol is missing', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'foo-bar'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + // type is 'none' + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'none' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: UrlParseError:/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by push when URL is malformed', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://foo.example.com:xxxx'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'none' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + it('throws InvalidURLFormatError by checkFetch when HTTP host is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://foo.bar.example.com/gitddb-plugin/sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'none' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch(/^URL format is invalid: Error: getaddrinfo ENOTFOUND/); + + await destroyDBs([dbA]); + }); + + describe('throws NetworkError', () => { + it('when IP address is invalid', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'https://127.0.0.1/gitddb-plugin/sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { + type: 'github', + }, + }).catch(error => error); + + expect(err).toBeInstanceOf(NetworkError); + expect(err.message).toMatch(/^Network error: Error: connect ECONNREFUSED/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError401AuthorizationRequired', () => { + it('when personal access token does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'github' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when connection setting not found', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-public.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { remoteUrl }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + + it('when invalid personal access token', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: 'foo-bar' }, + }).catch(error => error); + + expect(err).toBeInstanceOf(HTTPError401AuthorizationRequired); + expect(err.message).toMatch(/^HTTP Error: 401 Authorization required/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws HttpError404NotFound', () => { + it('when valid auth and repository does not exist', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'sync-test-invalid.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(HTTPError404NotFound); + expect(err.message).toMatch(/^HTTP Error: 404 Not Found/); + + await destroyDBs([dbA]); + }); + }); + + it('throws InvalidURLFormatError by createCredentialForGitHub', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = 'foo-bar'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(InvalidURLFormatError); + expect(err.message).toMatch( + /^URL format is invalid: http protocol required in createCredentialForGitHub/ + ); + + await destroyDBs([dbA]); + }); + + it('throws InvalidRepositoryURLError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'foo/bar/test.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + await expect( + push(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }) + ).rejects.toThrowError(InvalidRepositoryURLError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + await expect( + // @ts-ignore + push(dbA.workingDir, { remoteUrl, connection: { type: 'foo' } }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + it('throws InvalidAuthenticationTypeError with SSH', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + const remoteUrl = remoteURLBase + 'test-private.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + await expect( + // @ts-ignore + push(dbA.workingDir, { + remoteUrl, + connection: { + type: 'ssh', + publicKeyPath: path.resolve(userHome, '.ssh/invalid-test.pub'), + privateKeyPath: path.resolve(userHome, '.ssh/invalid-test'), + passPhrase: '', + }, + }) + ).rejects.toThrowError(InvalidAuthenticationTypeError); + + await destroyDBs([dbA]); + }); + + describe('throws HttpError403Forbidden', () => { + it('when access repository of another account with your account', async () => { + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + + // const remoteUrl = privateRepositoryOfAnotherUser; + const remoteUrl = 'https://github.com/sosuisen/git-documentdb.git'; + await createGitRemote(dbA.workingDir, remoteUrl, 'origin'); + + const err = await push(dbA.workingDir, { + remoteUrl, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(HTTPError403Forbidden); + expect(err.message).toMatch(/^HTTP Error: 403 Forbidden/); + + await destroyDBs([dbA]); + }); + }); + + describe('throws UnfetchedCommitExistsError', () => { + it('when unfetched commit exists', async () => { + console.log('#start'); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + serialId, + { + connection: { + type: 'github', + personalAccessToken: token, + engine: 'isomorphic-git', + }, + } + ); + console.log('#end'); + await dbB.put({ name: 'foo' }); + await syncB.tryPush(); + + const err = await push(dbA.workingDir, { + remoteUrl: syncA.remoteURL, + connection: { type: 'github', personalAccessToken: token }, + }).catch(error => error); + expect(err).toBeInstanceOf(UnfetchedCommitExistsError); + + await destroyDBs([dbA, dbB]); + }); + + it('Race condition of two push() calls throws UnfetchedCommitExistsError in validatePushResult', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + engine: 'isomorphic-git', + }, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + const syncB = await dbB.sync(options); + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + await expect( + Promise.all([ + push(dbA.workingDir, { + remoteUrl: syncA.remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + engine: 'isomorphic-git', + }, + }), + push(dbB.workingDir, { + remoteUrl: syncB.remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + engine: 'isomorphic-git', + }, + }), + ]) + ).rejects.toThrowError(UnfetchedCommitExistsError); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe('throws CannotConnectError', () => { + // NetworkError is thrown when network is not connected. + // CannotConnectError will be thrown when other unexpected cases. + }); +}); diff --git a/test/remote/3way_merge.test.ts b/test/remote/3way_merge.test.ts deleted file mode 100644 index dd98ecce..00000000 --- a/test/remote/3way_merge.test.ts +++ /dev/null @@ -1,1735 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test 3-way merge - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import { Err } from '../../src/error'; -import { threeWayMerge } from '../../src/remote/3way_merge'; -import { GitDocumentDB } from '../../src/git_documentdb'; -import { - FatDoc, - JsonDoc, - SyncResultMergeAndPush, - SyncResultResolveConflictsAndPush, -} from '../../src/types'; -import { - compareWorkingDirAndBlobs, - createClonedDatabases, - createDatabase, - destroyDBs, - getChangedFileDelete, - getChangedFileInsert, - getChangedFileUpdate, - getCommitInfo, - getWorkingDirDocs, - removeRemoteRepositories, -} from '../remote_utils'; -import { JSON_EXT } from '../../src/const'; - -const reposPrefix = 'test_3way_merge___'; -const localDir = `./test/database_3way_merge`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak of getCommitLogs() - // fs.removeSync(path.resolve(localDir)); -}); - -// This test needs environment variables: -// - GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe('', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - it('throws InvalidConflictsStateError', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours', - } - ); - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const commit = putResultA1.commit.oid; - const index = await dbA.repository()?.refreshIndex(); - await expect( - threeWayMerge(dbA, syncA, 'ours-diff', index!, 'foo', commit!, commit!, commit!, []) - ).rejects.toThrowError(Err.InvalidConflictStateError); - }); - - /** - * before: - * dbA : jsonA1 jsonA2 - * dbB : jsonB1 jsonB3 - * after : jsonB1 jsonA2 jsonB3 - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2: 1 - Accept theirs (insert) - * jsonB3: 2 - Accept ours (insert) - */ - it('resolves case 1 - Accept theirs (insert), case 2 - Accept ours (insert), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours', - } - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // B puts a new file - const jsonB3 = { _id: '3', name: 'fromB' }; - const putResultB3 = await dbB.put(jsonB3); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - putResultA2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - putResultB3, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([getChangedFileInsert(jsonA2, putResultA2)]); - - expect(syncResult1.changes.remote.length).toBe(2); - expect(syncResult1.changes.remote).toEqual( - expect.arrayContaining([ - getChangedFileInsert(jsonB3, putResultB3), - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - ]) - ); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2, jsonB3]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2, jsonB3]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: - * dbA : jsonA1 jsonA2 - * dbB : jsonB1 jsonA2 - * after : jsonB1 jsonA2 - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2: 3 - Accept both (insert) - */ - it('resolves case 3 - Accept both (insert), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours', - } - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // B puts the same file with the same contents - const putResultB2 = await dbB.put(jsonA2); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - putResultA2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - putResultB2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: - * dbA : jsonA1 - * dbB : jsonB1 - * after : jsonA1 - * - * 3-way merge: - * jsonA1: 5 - Conflict. Accept theirs (insert) - */ - it('resolves case 5 - Conflict. Accept theirs (insert)', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'theirs', - } - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - `resolve: 1${JSON_EXT}(insert,${putResultA1.fileOid.substr(0, 7)},theirs)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(insert,${putResultA1.fileOid.substr(0, 7)},theirs)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdate(jsonB1, putResultB1, jsonA1, putResultA1), - ]); - - expect(syncResult1.changes.remote.length).toBe(0); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultA1.fileOid, - type: 'json', - doc: jsonA1, - }, - strategy: 'theirs', - operation: 'insert', - }, - ]); - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA2 - * dbA : jsonA1 -jsonA2 - * dbB : jsonB1 -jsonA2 - * after : jsonB1 - * - * '-' means delete - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2: 6 - Accept both (delete) - */ - it('resolves case 6 - Accept both (delete), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA2 = { _id: '2', name: 'fromA' }; - await dbA.put(jsonA2); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts, deletes, and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - - const deleteResultA2 = await dbA.delete(jsonA2); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // B deletes the same file - const deleteResultB2 = await dbB.delete(jsonA2); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - deleteResultA2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - deleteResultB2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA2 - * dbA : jsonA1 - * dbB : jsonB1 -jsonA2 - * after : jsonB1 - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2: 7 - Accept ours (delete) - */ - it('resolves case 7 - Accept ours (delete), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA2 = { _id: '2', name: 'fromA' }; - await dbA.put(jsonA2); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // B deletes the same file - const deleteResultB2 = await dbB.delete(jsonA2); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - deleteResultB2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(2); - expect(syncResult1.changes.remote).toEqual( - expect.arrayContaining([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - getChangedFileDelete(jsonA2, deleteResultB2), - ]) - ); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : -jsonA1 - * result: - * - * '+' means update - * - * 3-way merge: - * jsonA1: 8 - Conflict. Accept ours (delete) - */ - it('resolves case 8 - Conflict. Accept ours (delete)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A updates and pushes - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B deletes and syncs - const deleteResultB1 = await dbB.delete(jsonA1); - - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(delete,${deleteResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - deleteResultB1, - `resolve: 1${JSON_EXT}(delete,${deleteResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileDelete(jsonA1dash, putResultA1dash), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: deleteResultB1.fileOid, - type: 'json', - doc: jsonA1, - }, - strategy: 'ours', - operation: 'delete', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : -jsonA1 - * result: jsonA1 - * - * '+' means update - * - * 3-way merge: - * jsonA1: 9 - Conflict. Accept theirs (update) - */ - it('resolves case 9 - Conflict. Accept ours (delete)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'theirs', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A updates and pushes - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B deletes and syncs - const deleteResultB1 = await dbB.delete(jsonA1); - - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(update,${putResultA1dash.fileOid.substr(0, 7)},theirs)`, - ]), - remote: getCommitInfo([ - deleteResultB1, - `resolve: 1${JSON_EXT}(update,${putResultA1dash.fileOid.substr(0, 7)},theirs)`, - ]), - }); - - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileInsert(jsonA1dash, putResultA1dash), - ]); - - expect(syncResult1.changes.remote.length).toBe(0); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultA1dash.fileOid, - type: 'json', - doc: jsonA1dash, - }, - strategy: 'theirs', - operation: 'update', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA2 - * dbA : jsonA1 -jsonA2 - * dbB : jsonB1 - * after : jsonB1 - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2:10 - Accept theirs (delete) - */ - it('resolves case 10 - Accept theirs (delete), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA2 = { _id: '2', name: 'fromA' }; - await dbA.put(jsonA2); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts, deletes, and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const deleteResultA2 = await dbA.delete(jsonA2); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - deleteResultA2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileDelete(jsonA2, deleteResultA2), - ]); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : -jsonA1 jsonA2 - * dbB : jsonB1 - * result: jsonB1 jsonA2 - * - * 3-way merge: - * jsonB1: 11 - Conflict. Accept ours (update) - * jsonA2: 1 - Accept theirs (insert) - */ - it('resolves case 11 - Conflict. Accept ours (update), case 1 - Accept theirs (insert), ', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A deletes the old file and puts a new file - const deleteResultA1 = await dbA.delete(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B updates the old file and syncs - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - deleteResultA1, - putResultA2, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([getChangedFileInsert(jsonA2, putResultA2)]); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([getChangedFileInsert(jsonB1, putResultB1)]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'update', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : -jsonA1 jsonA2 - * dbB : jsonB1 - * result: jsonA2 - * - * 3-way merge: - * jsonA1: 11 - Conflict. Accept theirs (delete) - * jsonA2: 1 - Accept theirs (insert) - */ - it('resolves case 12 - accept theirs (delete), case 1 - Accept theirs (insert)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync({ - ...syncA.options, - conflictResolutionStrategy: 'theirs', - }); - - // A deletes the old file and puts a new file - const deleteResultA1 = await dbA.delete(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B updates the old file and syncs - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - deleteResultA1, - putResultA2, - `resolve: 1${JSON_EXT}(delete,${deleteResultA1.fileOid.substr(0, 7)},theirs)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(delete,${deleteResultA1.fileOid.substr(0, 7)},theirs)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(2); - expect(syncResult1.changes.local).toEqual( - expect.arrayContaining([ - getChangedFileDelete(jsonB1, putResultB1), - getChangedFileInsert(jsonA2, putResultA2), - ]) - ); - - expect(syncResult1.changes.remote.length).toBe(0); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: deleteResultA1.fileOid, - type: 'json', - doc: jsonA1, - }, - strategy: 'theirs', - operation: 'delete', - }, - ]); - // Conflict occurs on 1.json - expect(getWorkingDirDocs(dbA)).toEqual([jsonA2]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA2 - * dbA : jsonA1 +jsonA2 - * dbB : jsonB1 +jsonA2 - * after : jsonB1 +jsonA2 - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2:13 - Accept both (update) - */ - it('resolves case 13 - Accept both (update), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const jsonA2dash = { _id: '2', name: 'updated' }; - const putResultA2dash = await dbA.put(jsonA2dash); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // B puts the same file with the same contents - const putResultB2 = await dbB.put(jsonA2dash); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - putResultA2dash, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - putResultB2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2dash]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - // case 14 - /** - * before: jsonA2 - * dbA : jsonA1 +jsonA2 - * dbB : jsonB1 jsonA2 - * after : jsonB1 +jsonA2 - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2:14 - Accept theirs (update) - */ - it('resolves case 14 - Accept theirs (update), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const jsonA2dash = { _id: '2', name: 'updated' }; - const putResultA2dash = await dbA.put(jsonA2dash); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // B puts the same file with the previous contents - const putResultB2 = await dbB.put(jsonA2); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - putResultA2dash, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - putResultB2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdate(jsonA2, putResultB2, jsonA2dash, putResultA2dash), - ]); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2dash]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA2 - * dbA : jsonA1 jsonA2 - * dbB : jsonB1 jsonB2 - * after : jsonB1 jsonB2 - * - * 3-way merge: - * jsonB1: 4 - Conflict. Accept ours (insert) - * jsonA2:15 - Accept ours (update) - */ - it('resolves case 15 - Accept ours (update), case 4 - Conflict. Accept ours (insert)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - // A puts the previous file and pushes - const putResultA2dash = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // B puts - const jsonB2 = { _id: '2', name: 'fromB' }; - const putResultB2 = await dbB.put(jsonB2); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - putResultA2dash, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - putResultB2, - `resolve: 1${JSON_EXT}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(2); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - getChangedFileUpdate(jsonA2, putResultA2dash, jsonB2, putResultB2), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'insert', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonB2]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : jsonB1 - * - * 3-way merge: - * jsonB1:16 - Conflict. Accept ours (update) - */ - it('resolves case 16 - Conflict. Accept ours (update)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1dash, putResultA1dash, jsonB1, putResultB1), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'update', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : +jsonA1 - * - * 3-way merge: - * jsonA1:17 - Conflict. Accept theirs (update) - */ - it('resolves case 17 - Conflict. Accept theirs (update)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'theirs', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync({ - ...syncA.options, - conflictResolutionStrategy: 'theirs', - }); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(update,${putResultA1dash.fileOid.substr(0, 7)},theirs)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(update,${putResultA1dash.fileOid.substr(0, 7)},theirs)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdate(jsonB1, putResultB1, jsonA1dash, putResultA1dash), - ]); - - expect(syncResult1.changes.remote.length).toBe(0); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultA1dash.fileOid, - type: 'json', - doc: jsonA1dash, - }, - strategy: 'theirs', - operation: 'update', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 jsonA2 jsonA3 - * dbA : +jsonA1 -jsonA2 +jsonA3 - * dbB : -jsonA1 +jsonB2 +jsonB3 - * result: jsonB2 jsonB3 - * - * 3-way merge: - * jsonA1: 8 - Conflict. Accept ours (delete) - * jsonB2: 4 - Conflict. Accept ours (insert) - * jsonB3:11 - Conflict. Accept ours (update) - */ - it('resolves many conflicts', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - const jsonA3 = { _id: '3', name: 'fromA' }; - const putResultA3 = await dbA.put(jsonA3); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A updates, deletes, updates, and pushes - - // change commit order for test - // 3 -> 1 -> 2 - const jsonA3dash = { _id: '3', name: 'updated' }; - const putResultA3dash = await dbA.put(jsonA3dash); - - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - - const deleteResultA2 = await dbA.delete(jsonA2); - - await syncA.tryPush(); - - // B deletes, updates, updates, and syncs - - // change commit order for test - // 3 -> 1 -> 2 - const jsonB3 = { _id: '3', name: 'fromB' }; - const putResultB3 = await dbB.put(jsonB3); - - const deleteResultB1 = await dbB.delete(jsonA1); - - const jsonB2 = { _id: '2', name: 'fromB' }; - const putResultB2 = await dbB.put(jsonB2); - - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA3dash, - putResultA1dash, - deleteResultA2, - `resolve: 1${JSON_EXT}(delete,${deleteResultB1.fileOid.substr( - 0, - 7 - )},ours), 2${JSON_EXT}(update,${putResultB2.fileOid.substr( - 0, - 7 - )},ours), 3${JSON_EXT}(update,${putResultB3.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB3, - deleteResultB1, - putResultB2, - `resolve: 1${JSON_EXT}(delete,${deleteResultB1.fileOid.substr( - 0, - 7 - )},ours), 2${JSON_EXT}(update,${putResultB2.fileOid.substr( - 0, - 7 - )},ours), 3${JSON_EXT}(update,${putResultB3.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(3); - expect(syncResult1.changes.remote).toEqual( - expect.arrayContaining([ - getChangedFileDelete(jsonA1dash, putResultA1dash), - getChangedFileInsert(jsonB2, putResultB2), - getChangedFileUpdate(jsonA3dash, putResultA3dash, jsonB3, putResultB3), - ]) - ); - - expect(syncResult1.conflicts).toEqual( - expect.arrayContaining([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: deleteResultB1.fileOid, - type: 'json', - doc: jsonA1, - }, - strategy: 'ours', - operation: 'delete', - }, - { - fatDoc: { - _id: '2', - name: '2.json', - fileOid: putResultB2.fileOid, - type: 'json', - doc: jsonB2, - }, - strategy: 'ours', - operation: 'update', - }, - { - fatDoc: { - _id: '3', - name: '3.json', - fileOid: putResultB3.fileOid, - type: 'json', - doc: jsonB3, - }, - strategy: 'ours', - operation: 'update', - }, - ]) - ); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB2, jsonB3]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB2, jsonB3]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : jsonB1 - * - * 3-way merge: - * jsonB1:16 - Conflict. Accept ours (update) - */ - it('resolves case 16 by user strategy function.', async () => { - const userStrategyByDate = (ours?: FatDoc, theirs?: FatDoc) => { - if (ours === undefined || theirs === undefined) { - throw new Error('Undefined document'); - } - if ((ours.doc as JsonDoc).date > (theirs.doc as JsonDoc).date) { - return 'ours'; - } - return 'theirs'; - }; - - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: userStrategyByDate, - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'updated', date: '2021/05/16' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'fromB', date: '2021/06/16' }; - const putResultB1 = await dbB.put(jsonB1); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1dash, putResultA1dash, jsonB1, putResultB1), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours', - operation: 'update', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : +jsonA1 - * - * 3-way merge: - * jsonA1:17 - Conflict. Accept theirs (update) - */ - it('resolves case 17 by user strategy function.', async () => { - const userStrategyByDate = (ours?: FatDoc, theirs?: FatDoc) => { - if (ours === undefined || theirs === undefined) { - throw new Error('Undefined document'); - } - if ((ours.doc as JsonDoc).date > (theirs.doc as JsonDoc).date) { - return 'ours'; - } - return 'theirs'; - }; - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: userStrategyByDate, - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync({ - ...syncA.options, - conflictResolutionStrategy: 'theirs', - }); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'updated', date: '2021/06/16' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'fromB', date: '2021/05/16' }; - const putResultB1 = await dbB.put(jsonB1); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(update,${putResultA1dash.fileOid.substr(0, 7)},theirs)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(update,${putResultA1dash.fileOid.substr(0, 7)},theirs)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdate(jsonB1, putResultB1, jsonA1dash, putResultA1dash), - ]); - - expect(syncResult1.changes.remote.length).toBe(0); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultA1dash.fileOid, - type: 'json', - doc: jsonA1dash, - }, - strategy: 'theirs', - operation: 'update', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); -}); diff --git a/test/remote/clone.test.ts b/test/remote/clone.test.ts deleted file mode 100644 index bbc28f18..00000000 --- a/test/remote/clone.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test clone - * by using GitHub Personal Access Token - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import { cloneRepository } from '../../src/remote/clone'; -import { removeRemoteRepositories } from '../remote_utils'; - -const reposPrefix = 'test_clone___'; -const localDir = `./test/database_clone`; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - fs.removeSync(path.resolve(localDir)); -}); - -// GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(' cloneRepository', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - // Remove remote - await removeRemoteRepositories(reposPrefix); - }); - - it('returns undefined when invalid RemoteOptions', async () => { - // @ts-ignore - await expect(cloneRepository('tmp')).resolves.toBeUndefined(); - await expect(cloneRepository('tmp', { remoteUrl: undefined })).resolves.toBeUndefined(); - }); -}); diff --git a/test/remote/combine.test.ts b/test/remote/combine.test.ts deleted file mode 100644 index 540de8cc..00000000 --- a/test/remote/combine.test.ts +++ /dev/null @@ -1,520 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test sync - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import git from 'isomorphic-git'; -import expect from 'expect'; -import parse from 'parse-git-config'; -import { DuplicatedFile } from '../../src/types'; -import { GitDocumentDB } from '../../src/git_documentdb'; -import { Err } from '../../src/error'; -import { - compareWorkingDirAndBlobs, - createDatabase, - destroyDBs, - destroyRemoteRepository, - getWorkingDirDocs, - removeRemoteRepositories, -} from '../remote_utils'; -import { sleep } from '../../src/utils'; -import { JSON_EXT } from '../../src/const'; - -const reposPrefix = 'test_combine___'; -const localDir = `./test/database_combine`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak of getCommitLogs() - // fs.removeSync(path.resolve(localDir)); -}); - -// This test needs environment variables: -// - GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe('', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - /** - * Combine database - */ - describe('Combining database', () => { - it('throws NoMergeBaseFoundError when combineDbStrategy is throw-error in [both] direction', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'throw-error', - syncDirection: 'both', - }); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - // trySync throws NoMergeBaseFoundError - await expect(dbB.sync(syncA.options)).rejects.toThrowError(Err.NoMergeBaseFoundError); - - // await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - // await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('commits with valid commit message for combine-head-with-theirs', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - // Need local commit to combine dbs with commit message. - const jsonB1 = { _id: '1', name: 'fromB' }; - await dbB.put(jsonB1); - - // Combine with remote db - await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( - Err.NoMergeBaseFoundError - ); - - const headCommitOid = await git.resolveRef({ - fs, - dir: dbB.workingDir, - ref: 'HEAD', - }); - const headCommit = await git.readCommit({ - fs, - dir: dbB.workingDir, - oid: headCommitOid, - }); - expect(headCommit.commit.message).toEqual(`combine database head with theirs\n`); - - await destroyDBs([dbA, dbB]); - }); - - it('succeeds when combine-head-with-theirs with empty local and empty remote', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - // Combine with remote db - await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( - Err.NoMergeBaseFoundError - ); - - // Put new doc to combined db. - const jsonB2 = { _id: '2', name: 'fromB' }; - await dbB.put(jsonB2); - - expect(getWorkingDirDocs(dbA)).toEqual([]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('succeeds combine-head-with-theirs with empty local and not empty remote', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.trySync(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - // Combine with remote db - await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( - Err.NoMergeBaseFoundError - ); - - // Put new doc to combined db. - const jsonB2 = { _id: '2', name: 'fromB' }; - await dbB.put(jsonB2); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('succeeds when combine-head-with-theirs with not empty local and empty remote', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - const jsonB1 = { _id: '1', name: 'fromB' }; - await dbB.put(jsonB1); - - // Combine with remote db - await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( - Err.NoMergeBaseFoundError - ); - - // Put new doc to combined db. - const jsonB2 = { _id: '2', name: 'fromB' }; - await dbB.put(jsonB2); - - expect(getWorkingDirDocs(dbA)).toEqual([]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('succeeds when combine-head-with-theirs with deep local and deep remote', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - const jsonA1 = { _id: 'deep/one', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.trySync(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - const jsonB2 = { - _id: 'item/box01F76SNGYBWA5PBAYR0GNNT3Y4/item01F76SP8HNANY5QAXZ53DEHXBJ', - name: 'fromB', - }; - await dbB.put(jsonB2); - - // Combine with remote db - await dbB.sync(syncA.options); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('returns SyncResult with duplicates when combine-head-with-theirs with not empty local and not empty remote', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - const dbIdA = dbA.dbId; - - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.trySync(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - const dbIdB = dbB.dbId; - expect(dbIdB).not.toBe(dbIdA); - - const jsonB1 = { _id: '1', name: 'fromB' }; - await dbB.put(jsonB1); - - const jsonB2 = { _id: '2', name: 'fromB' }; - await dbB.put(jsonB2); - - // Combine with remote db - const [sync, syncResult] = await dbB.sync(syncA.options, true); - - expect(dbB.dbId).toBe(dbIdA); - - // Put new doc to combined db. - const jsonB3 = { _id: '3', name: 'fromB' }; - await dbB.put(jsonB3); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - // jsonB1 is duplicated with postfix due to combine-head-with-theirs strategy - jsonB1._id = jsonB1._id + '-from-' + dbIdB; - const duplicatedB1 = await dbB.getFatDoc(jsonB1._id + JSON_EXT); - - expect(syncResult).toEqual({ - action: 'combine database', - duplicates: [ - { - original: { - _id: jsonA1._id, - name: jsonA1._id + JSON_EXT, - fileOid: putResultA1.fileOid, - type: 'json', - }, - duplicate: { - _id: jsonB1._id, - name: jsonB1._id + JSON_EXT, - fileOid: duplicatedB1?.fileOid, - type: 'json', - }, - }, - ], - }); - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA1, jsonB2, jsonB3]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('returns SyncResult with duplicates when combine-head-with-theirs with deep local and deep remote', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - const dbIdA = dbA.dbId; - - const jsonA1 = { _id: 'deep/one', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.trySync(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - const dbIdB = dbB.dbId; - expect(dbIdB).not.toBe(dbIdA); - - const jsonB1 = { _id: 'deep/one', name: 'fromB' }; - await dbB.put(jsonB1); - - const jsonB2 = { _id: '2', name: 'fromB' }; - await dbB.put(jsonB2); - - // Combine with remote db - const [sync, syncResult] = await dbB.sync(syncA.options, true); - - expect(dbB.dbId).toBe(dbIdA); - - // Put new doc to combined db. - const jsonB3 = { _id: '3', name: 'fromB' }; - await dbB.put(jsonB3); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - // jsonB1 is duplicated with postfix due to combine-head-with-theirs strategy - jsonB1._id = jsonB1._id + '-from-' + dbIdB; - const duplicatedB1 = await dbB.getFatDoc(jsonB1._id + JSON_EXT); - - expect(syncResult).toEqual({ - action: 'combine database', - duplicates: [ - { - original: { - _id: jsonA1._id, - name: jsonA1._id + JSON_EXT, - fileOid: putResultA1.fileOid, - type: 'json', - }, - duplicate: { - _id: jsonB1._id, - name: jsonB1._id + JSON_EXT, - fileOid: duplicatedB1?.fileOid, - type: 'json', - }, - }, - ], - }); - expect(getWorkingDirDocs(dbB)).toEqual([jsonB2, jsonB3, jsonB1, jsonA1]); - - const rawJSON = fs.readJSONSync(dbB.workingDir + '/deep/one.json'); - rawJSON._id = 'one'; // not 'deep/one' - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('invokes combine event with duplicates when combine-head-with-theirs with not empty local and not empty remote', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - let duplicatedFiles: DuplicatedFile[] = []; - syncA.on('combine', (duplicates: DuplicatedFile[]) => { - duplicatedFiles = [...duplicates]; - }); - - const dbIdA = dbA.dbId; - - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - - // Delete remote repository - await destroyRemoteRepository(syncA.remoteURL); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - const dbIdB = dbB.dbId; - - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - const jsonB2 = { _id: '2', name: 'fromB' }; - await dbB.put(jsonB2); - - // Create and push to new remote repository - const syncB = await dbB.sync(syncA.options); - // Combine database on A - await syncA.trySync().catch(async () => { - await dbA.destroy(); - }); - - jsonA1._id = jsonA1._id + '-from-' + dbIdA; - const duplicatedA1 = await dbA.getFatDoc(jsonA1._id + JSON_EXT); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonB1, jsonB2]); - // jsonA1 is duplicated with postfix due to combine-head-with-theirs strategy - - while (duplicatedFiles.length === 0) { - // eslint-disable-next-line no-await-in-loop - await sleep(3000); - } - expect(duplicatedFiles).toEqual([ - { - original: { - _id: jsonB1._id, - name: jsonB1._id + JSON_EXT, - fileOid: putResultB1.fileOid, - type: 'json', - }, - duplicate: { - _id: jsonA1._id, - name: jsonA1._id + JSON_EXT, - fileOid: duplicatedA1?.fileOid, - type: 'json', - }, - }, - ]); - - // Push combined db - await syncA.trySync(); - // Pull combined db - await syncB.trySync(); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB1, jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - it('copies author from local repository', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - combineDbStrategy: 'combine-head-with-theirs', - syncDirection: 'both', - }); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - const author = { - name: 'foo', - email: 'bar@localhost', - }; - dbB.author = author; - await dbB.saveAuthor(); - - // Combine with remote db - await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( - Err.NoMergeBaseFoundError - ); - - const config = parse.sync({ cwd: dbB.workingDir, path: '.git/config' }); - expect(config.user).toEqual(author); - - await destroyDBs([dbA, dbB]); - }); - }); -}); diff --git a/test/remote/json_patch_ot.test.ts b/test/remote/json_patch_ot.test.ts deleted file mode 100644 index acc85ee3..00000000 --- a/test/remote/json_patch_ot.test.ts +++ /dev/null @@ -1,1043 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { editOp, type } from 'ot-json1'; -import expect from 'expect'; -import { JsonDiff } from '../../src/remote/json_diff'; -import { JsonPatchOT } from '../../src/remote/json_patch_ot'; - -const primitiveDiff = new JsonDiff(); - -const textOTDiff = new JsonDiff({ - plainTextProperties: { text: true }, -}); - -const jPatch = new JsonPatchOT(); - -describe(' OT', () => { - describe('for primitive', () => { - it('applies patch (create)', () => { - const oldDoc = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - }; - const newDoc = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - age2: 'Heijo-kyo', - year2: 710, - current2: false, - }; - /* - const diff = { - age2: ['Heijo-kyo'], - year2: [710], - current2: [false], - }; - expect(primitiveDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - */ - // keys must be sorted by descendant order - const patch = [ - ['age2', { i: 'Heijo-kyo' }], - ['current2', { i: false }], - ['year2', { i: 710 }], - ]; - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (create)', () => { - const oldDoc = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - }; - const newDoc = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - age2: 'Heijo-kyo', - year2: 710, - current2: false, - }; - - const diff = { - age2: ['Heijo-kyo'], - year2: [710], - current2: [false], - }; - expect(primitiveDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - // keys must be sorted by descendant order - const patch = [ - ['age2', { i: 'Heijo-kyo' }], - ['current2', { i: false }], - ['year2', { i: 710 }], - ]; - - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - }); - - it('patches from diff (create)', () => { - const oldDoc = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - }; - const newDoc = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - age2: 'Heijo-kyo', - year2: 710, - current2: false, - }; - - expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( - newDoc - ); - }); - - it('merges independent changes (create)', () => { - const base = { - _id: 'nara', - age: 'Nara prefecture', - }; - - const ours = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - }; - - const theirs = { - _id: 'nara', - age: 'Nara prefecture', - age2: 'Heijo-kyo', - year2: 710, - current2: false, - }; - - const merged = { - _id: 'nara', - age: 'Nara prefecture', - year: 1887, - current: true, - age2: 'Heijo-kyo', - year2: 710, - current2: false, - }; - - const diffOurs = primitiveDiff.diff(base, ours); - const diffTheirs = primitiveDiff.diff(base, theirs); - - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - - it('merges independent changes (update)', () => { - const base = { - _id: 'nara', - age: 'Nara prefecture', - deer: 100, - }; - - // The number of deer has increased. - const ours = { - _id: 'nara', - age: 'Nara prefecture', - deer: 1000, - }; - - // The number of deer in Nara was small in the past. - const theirs = { - _id: 'nara', - age: 'Heijo-kyo', - deer: 100, - }; - - // This is correct as a merge result, but incorrect as a schema. - // 'age' and 'deer' are interdependent. - // It must be resolved by user. - const merged = { - _id: 'nara', - age: 'Heijo-kyo', - deer: 1000, - }; - - const diffOurs = primitiveDiff.diff(base, ours); - // console.log(diffOurs); - const diffTheirs = primitiveDiff.diff(base, theirs); - // console.log(diffTheirs); - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - }); - - describe('for text', () => { - it('applies patch (create)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - const newDoc = { - _id: 'nara', - text: 'abc123def', - }; - - const diff = { - text: [ - `@@ -1,6 +1,9 @@ - abc -+123 - def -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - // keys must be sorted by descendant order - const patch = ['text', { es: [3, '123'] }]; - // const op = editOp(['title'], 'text-unicode', ['My cool blog entry']); - // console.log(op); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('applies patch (replace)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - const newDoc = { - _id: 'nara', - text: 'aebdcf', - }; - - const diff = { - text: [ - `@@ -1,6 +1,6 @@ - a --bcde -+ebdc - f -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - // keys must be sorted by descendant order - const patch = ['text', { es: [1, { d: 4 }, 'ebdc'] }]; - // const op = editOp(['title'], 'text-unicode', ['My cool blog entry']); - // console.log(op); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('applies patch (move)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdefghijklmnopqrstuvwxyz0123456789', - }; - const newDoc = { - _id: 'nara', - text: 'abcdefg56789hijklmnopqrstuvwxyz01234', - }; - - const diff = { - text: [ - `@@ -1,15 +1,20 @@ - abcdefg -+56789 - hijklmno -@@ -29,13 +29,8 @@ - xyz01234 --56789 -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const op = editOp(['text'], 'text-unicode', [7, '56789']); - // console.log(op); - const op2 = editOp(['text'], 'text-unicode', [36, { d: 5 }]); - // console.log(op2); - const op3 = [op, op2].reduce(type.compose, null); - // console.log(op3); - - // const op = editOp(['title'], 'text-unicode', ['My cool blog entry']); - // console.log(op); - - expect(jPatch.apply(oldDoc, op3)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (from one character)', () => { - const oldDoc = { - _id: 'nara', - text: ' ', - }; - - const newDoc = { - _id: 'nara', - text: 'abc', - }; - const diff = { - text: [ - `@@ -1 +1,3 @@ -- -+abc -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - const patch = ['text', { es: [{ d: 1 }, 'abc'] }]; - - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (to one character)', () => { - const oldDoc = { - _id: 'nara', - text: 'abc', - }; - - const newDoc = { - _id: 'nara', - text: ' ', - }; - - const diff = { - text: [ - `@@ -1,3 +1 @@ --abc -+ -`, - 0, - 2, - ], - }; - - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [{ d: 3 }, ' '] }]; - - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (create)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - const newDoc = { - _id: 'nara', - text: 'abc123def', - }; - - const diff = { - text: [ - `@@ -1,6 +1,9 @@ - abc -+123 - def -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [3, '123'] }]; - - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (add to head of text)', () => { - const oldDoc = { - _id: 'nara', - text: 'abc', - }; - - const newDoc = { - _id: 'nara', - text: '123abc', - }; - const diff = { - text: [ - `@@ -1,3 +1,6 @@ -+123 - abc -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: ['123'] }]; - // expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (add to middle of text', () => { - const oldDoc = { - _id: 'nara', - text: 'abc', - }; - - const newDoc = { - _id: 'nara', - text: 'ab123c', - }; - const diff = { - text: [ - `@@ -1,3 +1,6 @@ - ab -+123 - c -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [2, '123'] }]; - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (add to tail of text', () => { - const oldDoc = { - _id: 'nara', - text: 'abc', - }; - - const newDoc = { - _id: 'nara', - text: 'abc123', - }; - const diff = { - text: [ - `@@ -1,3 +1,6 @@ - abc -+123 -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [3, '123'] }]; - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (delete from head of text)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - - const newDoc = { - _id: 'nara', - text: 'def', - }; - - const diff = { - text: [ - `@@ -1,6 +1,3 @@ --abc - def -`, - 0, - 2, - ], - }; - - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [{ d: 3 }] }]; - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (delete from middle of text)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - - const newDoc = { - _id: 'nara', - text: 'adef', - }; - - const diff = { - text: [ - `@@ -1,6 +1,4 @@ - a --bc - def -`, - 0, - 2, - ], - }; - - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [1, { d: 2 }] }]; - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (delete from tail of text', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - - const newDoc = { - _id: 'nara', - text: 'abc', - }; - - const diff = { - text: [ - `@@ -1,6 +1,3 @@ - abc --def -`, - 0, - 2, - ], - }; - - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [3, { d: 3 }] }]; - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (replace)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - const newDoc = { - _id: 'nara', - text: 'aebdcf', - }; - - const diff = { - text: [ - `@@ -1,6 +1,6 @@ - a --bcde -+ebdc - f -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [1, { d: 4 }, 'ebdc'] }]; - - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (move)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdefghijklmnopqrstuvwxyz0123456789', - }; - const newDoc = { - _id: 'nara', - text: 'abcdefg56789hijklmnopqrstuvwxyz01234', - }; - - const diff = { - text: [ - `@@ -1,15 +1,20 @@ - abcdefg -+56789 - hijklmno -@@ -29,13 +29,8 @@ - xyz01234 --56789 -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const op = editOp(['text'], 'text-unicode', [7, '56789']); - // console.log(op); - const op2 = editOp(['text'], 'text-unicode', [36, { d: 5 }]); - // console.log(op2); - const op3 = [op, op2].reduce(type.compose, null); - // console.dir(op3, { depth: 10 }); - - const patch = ['text', { es: [7, '56789', 24, { d: 5 }] }]; - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (escaped)', () => { - // google/diff-match-patch uses encodeURI() - const oldDoc = { - _id: 'nara', - text: '[abc]', - }; - - const newDoc = { - _id: 'nara', - text: `[abc]de`, - }; - - const diff = { - text: [ - `@@ -1,5 +1,7 @@ - %5Babc%5D -+de -`, - 0, - 2, - ], - }; - - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [5, `de`] }]; - - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (not escaped)', () => { - // google/diff-match-patch uses encodeURI() - const oldDoc = { - _id: 'nara', - text: ' ', - }; - - const newDoc = { - _id: 'nara', - text: `AZaz09;,/?:@&=+$-_.!~*'()#`, - }; - - const diff = { - text: [ - `@@ -1 +1,26 @@ -- -+AZaz09;,/?:@&=+$-_.!~*'()# -`, - 0, - 2, - ], - }; - - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - const patch = ['text', { es: [{ d: 1 }, `AZaz09;,/?:@&=+$-_.!~*'()#`] }]; - - expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); - - expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (two new lines)', () => { - const oldDoc = { - _id: 'nara', - text: 'abcdef', - }; - - const newDoc = { - _id: 'nara', - text: `ab\ncd\nef`, - }; - - const diff = { - text: [ - `@@ -1,6 +1,8 @@ - ab -+%0A - cd -+%0A - ef -`, - 0, - 2, - ], - }; - - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (long text with new lines)', () => { - const oldDoc = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - }; - - const newDoc = { - _id: 'littlewomen', - text: `[Xmas won't be Xmas without any presents,] -grumbled Jo, -lying on the rug. - -[It's so dreadful to be poor!] -sighed Meg, looking down at her old dress.`, - }; - - const diff = { - text: [ - `@@ -1,11 +1,6 @@ --%22Christ -+%5BX - mas -@@ -12,14 +12,9 @@ - be --Christ -+X - mas -@@ -34,17 +34,17 @@ - resents, --%22 -+%5D - %0Agrumble -@@ -48,17 +48,17 @@ - bled Jo, -- -+%0A - lying on -@@ -68,17 +68,18 @@ - e rug. %0A --%22 -+%0A%5B - It's so -@@ -102,9 +102,9 @@ - oor! --%22 -+%5D - %0Asig -`, - 0, - 2, - ], - }; - expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); - - // console.dir(jPatch.fromDiff(diff), { depth: 10 }); - - expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); - }); - - it('returns patch from diff (emoji)', () => { - // google/diff-match-patch uses encodeURI() - const oldDoc = { - _id: 'nara', - text: '😀😃😄😁😆😅', - }; - - const newDoc = { - _id: 'nara', - text: '😀😃a😄😁b😆😅', - }; - - expect(jPatch.patch(oldDoc, textOTDiff.diff(oldDoc, newDoc))).toStrictEqual(newDoc); - }); - - it('merges conflicted text: add', () => { - const base = { - _id: 'littlewomen', - text: '', - }; - - const ours = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -`, - }; - - const theirs = { - _id: 'littlewomen', - text: `"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - }; - - const merged = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - }; - - const diffOurs = textOTDiff.diff(base, ours); - // console.log(diffOurs); - const diffTheirs = textOTDiff.diff(base, theirs); - // console.log(diffTheirs); - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - - it('merges conflicted text: update and delete', () => { - const base = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - }; - - // update - const ours = { - _id: 'littlewomen', - text: `"Xmas won't be Xmas without any presents," -grumbled Jo, lying on the rug. -"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - }; - - // move - const theirs = { - _id: 'littlewomen', - text: `"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress. -"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug.`, - }; - - // Good result! - const merged = { - _id: 'littlewomen', - text: `"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress. -"Xmas won't be Xmas without any presents," -grumbled Jo, lying on the rug.`, - }; - - const diffOurs = textOTDiff.diff(base, ours); - // console.log(diffOurs); - const diffTheirs = textOTDiff.diff(base, theirs); - // console.log(diffTheirs); - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - - it('merges conflicted text: add and delete', () => { - const base = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -`, - }; - - const ours = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - }; - - const theirs = { - _id: 'littlewomen', - text: ``, - }; - - const merged = { - _id: 'littlewomen', - text: `"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - }; - - const diffOurs = textOTDiff.diff(base, ours); - // console.log(diffOurs); - const diffTheirs = textOTDiff.diff(base, theirs); - // console.log(diffTheirs); - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - - it('merges conflicted text: update and move', () => { - const base = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -`, - }; - - const ours = { - _id: 'littlewomen', - text: `"Xmas won't be Xmas without any presents," -grumbled Jo, lying on the rug.`, - }; - - const theirs = { - _id: 'littlewomen', - text: ``, - }; - - // ! NOTE: Not good result - const merged = { - _id: 'littlewomen', - text: `XX`, - }; - - const diffOurs = textOTDiff.diff(base, ours); - // console.log(diffOurs); - const diffTheirs = textOTDiff.diff(base, theirs); - // console.log(diffTheirs); - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - - it('merges only the selected property', () => { - const base = { - _id: 'littlewomen', - text: '', - not_merge: '', - }; - - const ours = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -`, - not_merge: 'from ours', - }; - - const theirs = { - _id: 'littlewomen', - text: `"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - not_merge: 'from theirs', - }; - - const merged = { - _id: 'littlewomen', - text: `"Christmas won't be Christmas without any presents," -grumbled Jo, lying on the rug. -"It's so dreadful to be poor!" -sighed Meg, looking down at her old dress.`, - not_merge: 'from ours', - }; - - const diffOurs = textOTDiff.diff(base, ours); - // console.log(diffOurs); - const diffTheirs = textOTDiff.diff(base, theirs); - // console.log(diffTheirs); - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - - it('merges non ASCII text', () => { - const base = { - _id: 'wagahai', - author: 'なし', - text: '吾輩は猫である。', - }; - - const ours = { - _id: 'wagahai', - author: '夏目漱石', - text: `吾輩は猫である。名前はまだ無い。`, - }; - - const theirs = { - _id: 'wagahai', - author: '太宰治', - text: `吾輩は犬である。`, - }; - - const merged = { - _id: 'wagahai', - author: '夏目漱石', - text: `吾輩は犬である。名前はまだ無い。`, - }; - - const diffOurs = textOTDiff.diff(base, ours); - // console.log(diffOurs); - const diffTheirs = textOTDiff.diff(base, theirs); - // console.log(diffTheirs); - const patchOurs = jPatch.fromDiff(diffOurs!); - // console.log(patchOurs); - const patchTheirs = jPatch.fromDiff(diffTheirs!); - // console.log(patchTheirs); - - expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); - }); - - it.skip('merges conflicted primitives: add', () => {}); - }); -}); diff --git a/test/remote/net.test.ts b/test/remote/net.test.ts deleted file mode 100644 index 8a7706b7..00000000 --- a/test/remote/net.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import expect from 'expect'; -import { Err } from '../../src/error'; -import { checkHTTP } from '../../src/remote/net'; - -describe(' checkHTTP', () => { - it('checks HTTPS connection', async () => { - await expect(checkHTTP('xyz', 3000)).rejects.toThrowError( - Err.HttpProtocolRequiredError - ); - const httpUrl = 'http://xyz.invalid/xyz/http_repos'; - await expect(checkHTTP(httpUrl, 3000)).rejects.toThrowError(Err.HTTPNetworkError); - const httpsUrl = 'https://xyz.invalid/xyz/http_repos'; - await expect(checkHTTP(httpsUrl, 3000)).rejects.toThrowError(Err.HTTPNetworkError); - - const validUrl = 'https://github.com/'; - await expect(checkHTTP(validUrl, 0)).rejects.toThrowError(Err.RequestTimeoutError); - await expect(checkHTTP(validUrl, -1, 0)).rejects.toThrowError(Err.SocketTimeoutError); - await expect(checkHTTP(validUrl, 10000)).resolves.toMatchObject({ - ok: true, - code: 200, - }); - }); -}); diff --git a/test/remote/remote_repository.test.ts b/test/remote/remote_repository.test.ts deleted file mode 100644 index e39e6c59..00000000 --- a/test/remote/remote_repository.test.ts +++ /dev/null @@ -1,842 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test remote_repository.ts - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import { Octokit } from '@octokit/rest'; -import expect from 'expect'; -import fs from 'fs-extra'; -import { monotonicFactory } from 'ulid'; -import { createCredential } from '../../src/remote/authentication'; -import { GitDocumentDB } from '../../src/git_documentdb'; -import { Err } from '../../src/error'; -import { NETWORK_RETRY, NETWORK_RETRY_INTERVAL } from '../../src/const'; -import { - createRemoteRepository, - destroyDBs, - destroyRemoteRepository, - removeRemoteRepositories, -} from '../remote_utils'; -import { RemoteRepository } from '../../src/remote/remote_repository'; -import { RemoteOptions } from '../../src/types'; - -const ulid = monotonicFactory(); -const monoId = () => { - return ulid(Date.now()); -}; - -const reposPrefix = 'test_remote_repository___'; -const localDir = `./test/database_remote_repository`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - fs.removeSync(path.resolve(localDir)); -}); - -// GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(' RemoteRepository', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - // Remove remote - await removeRemoteRepositories(reposPrefix); - }); - - describe(': create()', () => { - it('throws InvalidAuthenticationTypeError', () => { - const remoteURL = remoteURLBase + serialId(); - expect(() => { - const repo = new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - // @ts-ignore - type: 'gitlab', - }, - }); - }); - }); - - it('creates a remote repository on GitHub by personal access token', async () => { - const remoteURL = remoteURLBase + serialId(); - const octokit = new Octokit({ - auth: token, - }); - const urlArray = remoteURL.split('/'); - const owner = urlArray[urlArray.length - 2]; - const repo = urlArray[urlArray.length - 1]; - - await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }).create(); - await expect(octokit.repos.listBranches({ owner, repo })).resolves.not.toThrowError(); - }); - - it('creates a remote repository by url which ends with .git.', async () => { - let remoteURL = remoteURLBase + serialId(); - const octokit = new Octokit({ - auth: token, - }); - const urlArray = remoteURL.split('/'); - const owner = urlArray[urlArray.length - 2]; - const repo = urlArray[urlArray.length - 1]; - - remoteURL += '.git'; - await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }).create(); - await expect(octokit.repos.listBranches({ owner, repo })).resolves.not.toThrowError(); - }); - - it('creates a private remote repository', async () => { - const remoteURL = remoteURLBase + serialId(); - const octokit = new Octokit({ - auth: token, - }); - const urlArray = remoteURL.split('/'); - const owner = urlArray[urlArray.length - 2]; - const repo = urlArray[urlArray.length - 1]; - - await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - private: true, - }, - }).create(); - const repos = await octokit.repos.get({ owner, repo }); - expect(repos.data.private).toBeTruthy(); - }); - - it('creates a private remote repository by default', async () => { - const remoteURL = remoteURLBase + serialId(); - const octokit = new Octokit({ - auth: token, - }); - const urlArray = remoteURL.split('/'); - const owner = urlArray[urlArray.length - 2]; - const repo = urlArray[urlArray.length - 1]; - - await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }).create(); - const repos = await octokit.repos.get({ owner, repo }); - expect(repos.data.private).toBeTruthy(); - }); - - it('creates a public remote repository', async () => { - const remoteURL = remoteURLBase + serialId(); - const octokit = new Octokit({ - auth: token, - }); - const urlArray = remoteURL.split('/'); - const owner = urlArray[urlArray.length - 2]; - const repo = urlArray[urlArray.length - 1]; - - await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - private: false, - }, - }).create(); - const repos = await octokit.repos.get({ owner, repo }); - expect(repos.data.private).toBeFalsy(); - }); - - it('throws UndefinedPersonalAccessTokenError()', async () => { - const remoteURL = remoteURLBase + serialId(); - - await expect( - new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: undefined, - }, - }).create() - ).rejects.toThrowError(Err.UndefinedPersonalAccessTokenError); - }); - - it('throws PersonalAccessTokenForAnotherAccountError()', async () => { - const readonlyURL = 'https://github.com/sosuisen/' + serialId(); - - await expect( - new RemoteRepository({ - remoteUrl: readonlyURL, - connection: { - type: 'github', - personalAccessToken: token, // This is valid but for another account. - }, - }).create() - ).rejects.toThrowError(Err.PersonalAccessTokenForAnotherAccountError); - }); - - it(`throws CannotConnectError() with ${NETWORK_RETRY} retries`, async () => { - const remoteURL = remoteURLBase + serialId(); - await createRemoteRepository(remoteURL); - - const error = await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }) - .create() - .catch(err => err); - expect(error).toBeInstanceOf(Err.CannotConnectError); - // This may be tested by using sinon.spy - expect((error as Err.CannotConnectError).retry).toBe(NETWORK_RETRY); - }); - - it('throws AuthenticationTypeNotAllowCreateRepositoryError()', async () => { - const remoteURL = remoteURLBase + serialId(); - - await expect( - new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'none', - }, - }).create() - ).rejects.toThrowError(Err.AuthenticationTypeNotAllowCreateRepositoryError); - }); - }); - - describe(': destroy()', () => { - it('removes a remote repository on GitHub by personal access token', async () => { - const remoteURL = remoteURLBase + serialId(); - - await createRemoteRepository(remoteURL); - const octokit = new Octokit({ - auth: token, - }); - const urlArray = remoteURL.split('/'); - const owner = urlArray[urlArray.length - 2]; - const repo = urlArray[urlArray.length - 1]; - - await destroyRemoteRepository(remoteURL); - - await expect(octokit.repos.listBranches({ owner, repo })).rejects.toThrowError(); - }); - - it('throws UndefinedPersonalAccessTokenError()', async () => { - const remoteURL = remoteURLBase + serialId(); - - await expect( - new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: undefined, - }, - }).destroy() - ).rejects.toThrowError(Err.UndefinedPersonalAccessTokenError); - }); - - it(`throws CannotConnectError() with ${NETWORK_RETRY_INTERVAL} retries`, async () => { - const remoteURL = remoteURLBase + serialId(); - - const error = await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }) - .destroy() - .catch(err => err); - expect(error).toBeInstanceOf(Err.CannotConnectError); - expect((error as Err.CannotConnectError).retry).toBe(NETWORK_RETRY); - }); - - it('throws AuthenticationTypeNotAllowCreateRepositoryError()', async () => { - const remoteURL = remoteURLBase + serialId(); - - await expect( - new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'none', - }, - }).destroy() - ).rejects.toThrowError(Err.AuthenticationTypeNotAllowCreateRepositoryError); - }); - }); - - describe(': _getOrCreateGitRemote()', () => { - it('returns "add" when origin is undefined', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - expect(result).toBe('add'); - - destroyDBs([gitDDB]); - }); - - it('returns "change" when another origin exists', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - await remoteRepos['_getOrCreateGitRemote'](gitDDB.repository()!, remoteURL); - - const remoteURL2 = remoteURLBase + serialId(); - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL2 - ); - expect(result).toBe('change'); - - destroyDBs([gitDDB]); - }); - - it('returns "exist" when the same origin exists', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - await remoteRepos['_getOrCreateGitRemote'](gitDDB.repository()!, remoteURL); - - const remoteURL2 = remoteURLBase + serialId(); - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - expect(result).toBe('exist'); - - destroyDBs([gitDDB]); - }); - }); - - describe(': _checkFetch()', () => { - it('returns exist', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - await createRemoteRepository(remoteURL); - const cred = createCredential({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }); - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkFetch'](remote, cred)).resolves.toBe('exist'); - - destroyDBs([gitDDB]); - }); - - it('throws InvalidURLError when a url starts with git@', async () => { - const remoteURL = 'git@github.com/xyz/' + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - - const cred = createCredential({ - remoteUrl: remoteURLBase + serialId(), - connection: { - type: 'github', - personalAccessToken: token, - }, - }); - - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkFetch'](remote, cred)).rejects.toThrowError( - Err.InvalidURLError - ); - - destroyDBs([gitDDB]); - }); - - it('throws InvalidURLError when a url starts invalid scheme', async () => { - const remoteURL = 'xttp://github.com/xyz/' + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - - const cred = createCredential({ - remoteUrl: remoteURLBase + serialId(), - connection: { - type: 'github', - personalAccessToken: token, - }, - }); - - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkFetch'](remote, cred)).rejects.toThrowError( - Err.InvalidURLError - ); - - destroyDBs([gitDDB]); - }); - - it('throws InvalidURLError when a host name is invalid', async () => { - const remoteURL = 'http://github.test/xyz/' + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - - const cred = createCredential({ - remoteUrl: remoteURLBase + serialId(), - connection: { - type: 'github', - personalAccessToken: token, - }, - }); - - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkFetch'](remote, cred)).rejects.toThrowError( - Err.InvalidURLError - ); - - destroyDBs([gitDDB]); - }); - - it('throws RepositoryNotFoundError when a remote repository does not exist', async () => { - const remoteURL = 'http://github.com/xyz/' + monoId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - - const cred = createCredential({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }); - - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkFetch'](remote, cred)).rejects.toThrowError( - Err.RemoteRepositoryNotFoundError - ); - - destroyDBs([gitDDB]); - }); - - it('throws FetchPermissionDeniedError when ssh key pair does not exist', async () => { - const remoteURL = 'http://github.com/xyz/' + monoId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - - const cred = createCredential({ - remoteUrl: remoteURL, - connection: { - type: 'ssh', - privateKeyPath: '/not/exist', - publicKeyPath: '/not/exist', - }, - }); - - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkFetch'](remote, cred)).rejects.toThrowError( - Err.FetchPermissionDeniedError - ); - - destroyDBs([gitDDB]); - }); - - it.skip('throws Error when private repository'); - - it.skip('throws FetchPermissionError when invalid ssh key pair exists'); - }); - - describe(': _checkPush()', () => { - it('returns ok', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - await createRemoteRepository(remoteURL); - const cred = createCredential({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }); - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkPush'](remote, cred)).resolves.toBe('ok'); - - destroyDBs([gitDDB]); - }); - - it('throws PushPermissionDeniedError when personalAccessToken is invalid', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - await new RemoteRepository({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }).create(); - - const cred = createCredential({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token + '_invalid', - }, - }); - // eslint-disable-next-line dot-notation - const error = await remoteRepos['_checkPush'](remote, cred).catch(err => err); - if (error instanceof Err.PushConnectionFailedError) { - // Notice that it sometimes throw Err.RemoteRepositoryNotFoundError - } - else { - expect(error).toBeInstanceOf(Err.RemoteRepositoryNotFoundError); - } - - destroyDBs([gitDDB]); - }); - - it("throws RemoteRepositoryNotFoundError when try to push to others' repository", async () => { - const remoteURL = 'https://github.com/sosuisen/git-documentdb'; - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const remoteRepos = new RemoteRepository({ - remoteUrl: remoteURL, - }); - // You can test private members by array access. - // eslint-disable-next-line dot-notation - const [result, remote] = await remoteRepos['_getOrCreateGitRemote']( - gitDDB.repository()!, - remoteURL - ); - const cred = createCredential({ - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }); - // eslint-disable-next-line dot-notation - await expect(remoteRepos['_checkPush'](remote, cred)).rejects.toThrowError( - Err.RemoteRepositoryNotFoundError - ); - - destroyDBs([gitDDB]); - }); - }); - - describe(': connect()', () => { - it(`returns ['add', 'create'] when both local and GitHub repository do not exist`, async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - - const remoteOptions: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - // @ts-ignore - const remoteRepos = new RemoteRepository(remoteOptions); - const cred = createCredential(remoteOptions); - const onlyFetch = true; - await expect( - remoteRepos.connect(gitDDB.repository()!, cred, onlyFetch) - ).resolves.toEqual(['add', 'create']); - - destroyDBs([gitDDB]); - }); - - it(`returns ['add', 'exist'] when a local repository does not exist and a GitHub repository exists`, async () => { - const readonlyURL = 'https://github.com/sosuisen/git-documentdb'; - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - - const remoteOptions: RemoteOptions = { - remoteUrl: readonlyURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - // @ts-ignore - const remoteRepos = new RemoteRepository(remoteOptions); - const cred = createCredential(remoteOptions); - const onlyFetch = true; - await expect( - remoteRepos.connect(gitDDB.repository()!, cred, onlyFetch) - ).resolves.toEqual(['add', 'exist']); - - destroyDBs([gitDDB]); - }); - - it(`throws FetchConnectionFailedError when remote url is invalid`, async () => { - const readonlyURL = 'https://github.test/invalid/host'; - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - - const remoteOptions: RemoteOptions = { - remoteUrl: readonlyURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - // @ts-ignore - const remoteRepos = new RemoteRepository(remoteOptions); - const cred = createCredential(remoteOptions); - const onlyFetch = true; - await expect( - remoteRepos.connect(gitDDB.repository()!, cred, onlyFetch) - ).rejects.toThrowError(Err.FetchConnectionFailedError); - - destroyDBs([gitDDB]); - }); - - it(`throws CannotCreateRemoteRepositoryError when a personal access token is for another account`, async () => { - const readonlyURL = 'https://github.com/sosuisen/' + serialId(); - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - - const remoteOptions: RemoteOptions = { - remoteUrl: readonlyURL, - connection: { - type: 'github', - personalAccessToken: token, // It is valid but for another account - }, - }; - // @ts-ignore - const remoteRepos = new RemoteRepository(remoteOptions); - const cred = createCredential(remoteOptions); - const onlyFetch = true; - await expect( - remoteRepos.connect(gitDDB.repository()!, cred, onlyFetch) - ).rejects.toThrowError(Err.CannotCreateRemoteRepositoryError); - - destroyDBs([gitDDB]); - }); - - it(`to a read only repository throws PushConnectionFailedError when onlyFetch is false`, async () => { - const readonlyURL = 'https://github.com/sosuisen/git-documentdb'; - const dbName = monoId(); - const gitDDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - - const remoteOptions: RemoteOptions = { - remoteUrl: readonlyURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - // @ts-ignore - const remoteRepos = new RemoteRepository(remoteOptions); - const cred = createCredential(remoteOptions); - const onlyFetch = false; - await expect( - remoteRepos.connect(gitDDB.repository()!, cred, onlyFetch) - ).rejects.toThrowError(Err.PushConnectionFailedError); - - destroyDBs([gitDDB]); - }); - }); -}); diff --git a/test/remote/sync.test.ts b/test/remote/sync.test.ts deleted file mode 100644 index 24ab2557..00000000 --- a/test/remote/sync.test.ts +++ /dev/null @@ -1,495 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test constructor - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import { Octokit } from '@octokit/rest'; -import expect from 'expect'; -import { MINIMUM_SYNC_INTERVAL } from '../../src/const'; -import { GitDocumentDB } from '../../src/git_documentdb'; -import { RemoteOptions } from '../../src/types'; -import { Err } from '../../src/error'; -import { Sync, syncImpl } from '../../src/remote/sync'; -import { destroyDBs, removeRemoteRepositories } from '../remote_utils'; - -const reposPrefix = 'test_sync_constructor___'; -const localDir = `./test_intg/database_sync`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - fs.removeSync(path.resolve(localDir)); -}); - -// GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(' Sync#constructor()', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - // Remove remote - await removeRemoteRepositories(reposPrefix); - }); - - // it.only('Run this test with .only to just remove remote repositories.', async () => { await removeRemoteRepositories('test_'); }); - - /** - * Tests for constructor - */ - it('set live to false by default', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - const sync = new Sync(gitDDB, options); - expect(sync.options.live).toBe(false); - - destroyDBs([gitDDB]); - }); - - it('set syncDirection to both by default', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - const sync = new Sync(gitDDB, options); - expect(sync.options.syncDirection).toBe('both'); - - destroyDBs([gitDDB]); - }); - - it('set combineDbStrategy to combine-head-with-theirs by default', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - const sync = new Sync(gitDDB, options); - expect(sync.options.combineDbStrategy).toBe('combine-head-with-theirs'); - - destroyDBs([gitDDB]); - }); - - it('set includeCommits to false by default', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - const sync = new Sync(gitDDB, options); - expect(sync.options.includeCommits).toBe(false); - - destroyDBs([gitDDB]); - }); - - it('set conflictResolutionStrategy to ours-diff by default', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - const sync = new Sync(gitDDB, options); - expect(sync.options.conflictResolutionStrategy).toBe('ours-diff'); - - destroyDBs([gitDDB]); - }); - - it('accepts remoteURL which ends with .git', async () => { - const remoteURL = remoteURLBase + serialId() + '.git'; - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - expect(() => new Sync(gitDDB, options)).not.toThrowError(); - - destroyDBs([gitDDB]); - }); - - it('throws UndefinedRemoteURLError when remoteURL is undefined.', async () => { - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - connection: { - type: 'github', - personalAccessToken: '', - }, - }; - expect(() => new Sync(gitDDB, options)).toThrowError(Err.UndefinedRemoteURLError); - await gitDDB.destroy(); - }); - - it('throws HttpProtocolRequiredError when remoteURL starts with ssh://', async () => { - const dbName = serialId(); - const remoteURL = 'ssh://github.com/'; - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: 'foobar', - }, - }; - expect(() => new Sync(gitDDB, options)).toThrowError(Err.HttpProtocolRequiredError); - await gitDDB.destroy(); - }); - - it('throws UndefinedPersonalAccessTokenError', async () => { - const dbName = serialId(); - const remoteURL = remoteURLBase + serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: '', - }, - }; - expect(() => new Sync(gitDDB, options)).toThrowError( - Err.UndefinedPersonalAccessTokenError - ); - await gitDDB.destroy(); - }); - - it('does not throw UndefinedPersonalAccessTokenError when syncDirections is "pull" ', async () => { - const dbName = serialId(); - const remoteURL = remoteURLBase + serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'pull', - connection: { - type: 'github', - personalAccessToken: '', - }, - }; - expect(() => new Sync(gitDDB, options)).not.toThrowError( - Err.UndefinedPersonalAccessTokenError - ); - await gitDDB.destroy(); - }); - - it('throws InvalidRepositoryURLError when url does not show a repository.', async () => { - const dbName = serialId(); - const remoteURL = 'https://github.com/'; - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: 'foobar', - }, - }; - expect(() => new Sync(gitDDB, options)).toThrowError(Err.InvalidRepositoryURLError); - await gitDDB.destroy(); - }); - - it('throws IntervalTooSmallError when interval is less than minimumSyncInterval.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const invalid_options: RemoteOptions = { - remoteUrl: remoteURL, - interval: MINIMUM_SYNC_INTERVAL - 1, - connection: { - type: 'github', - personalAccessToken: '', - }, - }; - expect(() => new Sync(gitDDB, invalid_options)).toThrowError(Err.IntervalTooSmallError); - await gitDDB.destroy(); - - await gitDDB.open(); - const valid_options: RemoteOptions = { - remoteUrl: remoteURL, - interval: MINIMUM_SYNC_INTERVAL, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - expect(() => new Sync(gitDDB, valid_options)).not.toThrowError(); - - await gitDDB.destroy(); - }); - - it('throws SyncIntervalLessThanOrEqualToRetryIntervalError', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const retryInterval = 5000; - const options: RemoteOptions = { - remoteUrl: remoteURL, - interval: retryInterval - 1, - retryInterval, - connection: { - type: 'github', - personalAccessToken: token, - }, - }; - // less than - expect(() => new Sync(gitDDB, options)).toThrowError( - Err.SyncIntervalLessThanOrEqualToRetryIntervalError - ); - await gitDDB.destroy(); - - // equal to - await gitDDB.open(); - options.interval = retryInterval; - expect(() => new Sync(gitDDB, options)).toThrowError( - Err.SyncIntervalLessThanOrEqualToRetryIntervalError - ); - await gitDDB.destroy(); - - // more than - await gitDDB.open(); - // eslint-disable-next-line require-atomic-updates - options.interval = retryInterval + 1; - expect(() => new Sync(gitDDB, options)).not.toThrowError(); - - await gitDDB.destroy(); - }); -}); - -maybe(' init()', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - // Remove remote - await removeRemoteRepositories(reposPrefix); - }); - - it('throws RemoteRepositoryConnectError.', async () => { - const dbName = serialId(); - const remoteURL = - 'https://github.com/sosuisen/foobar_test_for_remote_repository_connect_error'; - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: 'foo', - }, - }; - const sync = new Sync(gitDDB, options); - // - await expect(sync.init(gitDDB.repository()!)).rejects.toThrowError( - Err.RemoteRepositoryConnectError - ); - await gitDDB.destroy(); - }); -}); - -maybe(' syncImpl()', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - // Remove remote - await removeRemoteRepositories(reposPrefix); - }); - - it('throws RepositoryNotOpenError.', async () => { - const dbName = serialId(); - const remoteURL = remoteURLBase + serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await expect( - syncImpl.call(gitDDB, { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }) - ).rejects.toThrowError(Err.RepositoryNotOpenError); - await gitDDB.destroy(); - }); - - it('creates a remote repository on GitHub by using personal access token', async () => { - const remoteURL = remoteURLBase + serialId(); - - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - // Check dbInfo - await dbA.sync(options); - - // Check remote - const octokit = new Octokit({ - auth: token, - }); - const urlArray = remoteURL.split('/'); - const owner = urlArray[urlArray.length - 2]; - const repo = urlArray[urlArray.length - 1]; - await expect(octokit.repos.listBranches({ owner, repo })).resolves.not.toThrowError(); - - destroyDBs([dbA]); - }); -}); - -maybe(' tryPush()', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - // Remove remote - await removeRemoteRepositories(reposPrefix); - }); - - it('throws PushNotAllowedError.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbName = serialId(); - const gitDDB: GitDocumentDB = new GitDocumentDB({ - dbName, - localDir, - }); - await gitDDB.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { - type: 'github', - personalAccessToken: token, - }, - syncDirection: 'pull', - }; - const sync = new Sync(gitDDB, options); - await await expect(sync.init(gitDDB.repository()!)).rejects.toThrowError( - Err.PushNotAllowedError - ); - - destroyDBs([gitDDB]); - }); -}); diff --git a/test/remote/sync_events.test.ts b/test/remote/sync_events.test.ts deleted file mode 100644 index 35a0aa80..00000000 --- a/test/remote/sync_events.test.ts +++ /dev/null @@ -1,1185 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test synchronization events - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import sinon from 'sinon'; -import { - ChangedFile, - RemoteOptions, - SyncResult, - SyncResultFastForwardMerge, - SyncResultMergeAndPush, - SyncResultPush, - TaskMetadata, -} from '../../src/types'; -import { sleep } from '../../src/utils'; -import { - compareWorkingDirAndBlobs, - createClonedDatabases, - createDatabase, - destroyDBs, - destroyRemoteRepository, - getChangedFileDelete, - getChangedFileInsert, - getChangedFileUpdate, - getCommitInfo, - getWorkingDirDocs, - removeRemoteRepositories, -} from '../remote_utils'; -import { GitDocumentDB } from '../../src/git_documentdb'; -import { Sync } from '../../src/remote/sync'; -import { Err } from '../../src/error'; -import { MINIMUM_SYNC_INTERVAL, NETWORK_RETRY } from '../../src/const'; -import { pushWorker } from '../../src/remote/push_worker'; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const pushWorker_module = require('../../src/remote/push_worker'); - -const reposPrefix = 'test_sync_events___'; -const localDir = `./test/database_sync_events`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -// Use sandbox to restore stub and spy in parallel mocha tests -let sandbox: sinon.SinonSandbox; -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); - sandbox = sinon.createSandbox(); -}); - -afterEach(function () { - sandbox.restore(); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak of getCommitLogs() - // fs.removeSync(path.resolve(localDir)); -}); - -// GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(' [event]', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - /** - * Events - */ - describe('change', () => { - it('occurs once', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B syncs - let result: SyncResultFastForwardMerge | undefined; - let changeTaskId = ''; - syncB.on('change', (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - result = syncResult as SyncResultFastForwardMerge; - changeTaskId = taskMetadata.taskId; - }); - let complete = false; - let endTaskId = ''; - syncB.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(result!.action).toBe('fast-forward merge'); - - expect(result!.commits).toMatchObject({ - local: getCommitInfo([putResult1]), - }); - - expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); - - expect(changeTaskId).toBe(endTaskId); - - await destroyDBs([dbA, dbB]); - }); - - it('is propagated between local and remote sites', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.trySync(); - - // B puts and pushes - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - let resultA: SyncResultFastForwardMerge | undefined; - let completeA = false; - syncA.on('change', (syncResult: SyncResult) => { - resultA = syncResult as SyncResultFastForwardMerge; - console.log('A: ' + resultA.action); - if (resultA.action === 'fast-forward merge') { - completeA = true; - } - }); - - let resultB: SyncResultFastForwardMerge | undefined; - syncB.on('change', (syncResult: SyncResult) => { - resultB = syncResult as SyncResultFastForwardMerge; - console.log('B: ' + resultB.action); - }); - let completeB = false; - syncB.on('complete', () => { - completeB = true; - }); - - syncA.resume({ ...syncA.options, interval: 3000 }); - syncB.resume({ ...syncA.options, interval: 3000 }); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!completeA || !completeB) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(resultA!.action).toBe('fast-forward merge'); - - expect(resultA!.changes.local).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), - ]); - - expect(resultB!.action).toBe('resolve conflicts and push'); - - expect(resultB!.changes.local).toEqual([]); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 jsonA2 - * dbA : -jsonA1 -jsonA2 - * dbB : jsonB3 - * after : jsonB3 - */ - it('occurs with every retry', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - await dbA.put({ _id: '1' }); - await syncA.tryPush(); - - await dbB.put({ _id: '2' }); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.onFirstCall().rejects(new Err.UnfetchedCommitExistsError()); - - const resultsB: SyncResult[] = []; - syncB.on('change', (result: SyncResult) => { - if (resultsB.length === 0) { - // Restore stub after first change event. - stubPush.restore(); - } - // console.log('B: ' + JSON.stringify(result)); - resultsB.push(result); - }); - await syncB.trySync(); - - await sleep(syncA.options.retryInterval! + 5000); - expect(resultsB.length).toBe(2); - expect(resultsB[0].action).toBe('merge and push error'); - expect(resultsB[1].action).toBe('push'); - - await destroyDBs([dbA, dbB]); - }); - - it('is followed by localChange', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B syncs - let changes: ChangedFile[] = []; - let changeTaskId = ''; - syncB.on('localChange', (localChanges: ChangedFile[], taskMetadata: TaskMetadata) => { - changes = localChanges; - changeTaskId = taskMetadata.taskId; - }); - let complete = false; - let endTaskId = ''; - syncB.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(changes.length).toBe(1); - expect(changes).toEqual([getChangedFileInsert(jsonA1, putResult1)]); - - expect(changeTaskId).toBe(endTaskId); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 jsonA2 - * dbA : -jsonA1 -jsonA2 - * dbB : jsonB3 - * after : jsonB3 - */ - it('occurs localChanges when SyncResultMergeAndPushError', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - await dbA.put({ _id: '1' }); - await syncA.tryPush(); - - await dbB.put({ _id: '2' }); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.onFirstCall().rejects(new Err.UnfetchedCommitExistsError()); - - const localChangesB: ChangedFile[][] = []; - syncB.on('localChange', (changes: ChangedFile[]) => { - if (localChangesB.length === 0) { - // Restore stub after first change event. - stubPush.restore(); - } - localChangesB.push(changes); - }); - - await syncB.trySync(); - - await sleep(syncB.options.retryInterval! + 5000); - expect(localChangesB.length).toBe(1); - - await syncB.trySync(); - }); - - it('is followed by remoteChange', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - let changes: ChangedFile[] = []; - let changeTaskId = ''; - syncB.on( - 'remoteChange', - (remoteChanges: ChangedFile[], taskMetadata: TaskMetadata) => { - changes = remoteChanges; - changeTaskId = taskMetadata.taskId; - } - ); - let complete = false; - let endTaskId = ''; - syncB.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - - // B puts and syncs - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResult1 = await dbB.put(jsonB1); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(changes.length).toBe(1); - - expect(changes).toEqual([getChangedFileInsert(jsonB1, putResult1)]); - - expect(changeTaskId).toBe(endTaskId); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 jsonA2 - * dbA : -jsonA1 -jsonA2 - * dbB : jsonB3 - * after : jsonB3 - */ - it('occurs remoteChanges after SyncResultMergeAndPushError', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - await dbA.put({ _id: '1' }); - await syncA.tryPush(); - - await dbB.put({ _id: '2' }); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.onFirstCall().rejects(new Err.UnfetchedCommitExistsError()); - - let firstChange = true; - syncB.on('change', (changes: ChangedFile[]) => { - if (firstChange) { - firstChange = false; - // Restore stub after first change event. - stubPush.restore(); - } - }); - const remoteChangesB: ChangedFile[][] = []; - syncB.on('remoteChange', (changes: ChangedFile[]) => { - remoteChangesB.push(changes); - }); - - await syncB.trySync(); - - await sleep(syncB.options.retryInterval! + 5000); - expect(remoteChangesB.length).toBe(1); - - await syncB.trySync(); - }); - }); - - describe('filtered by collectionPath', () => { - it('occurs change and localChange events', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const col01 = dbA.collection('col01'); - const col02 = dbA.collection('col02'); - const jsonA1 = { _id: '1', name: 'fromA' }; - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult1 = await col01.put(jsonA1); - const putResult2 = await col02.put(jsonA2); - - const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; - const putResult1dash = { ...putResult1, _id: 'col01/1' }; - const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; - const putResult2dash = { ...putResult2, _id: 'col02/2' }; - - await syncA.tryPush(); - - // B syncs - let col01Result: SyncResultFastForwardMerge | undefined; - let col01ChangeTaskId: string | undefined; - syncB.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - col01Result = syncResult as SyncResultFastForwardMerge; - col01ChangeTaskId = taskMetadata.taskId; - }, - 'col01' - ); - - let changedFiles: ChangedFile[]; - syncB.on( - 'localChange', - (files: ChangedFile[], taskMetadata: TaskMetadata) => { - changedFiles = files; - }, - 'col02' - ); - - let rootResult: SyncResultFastForwardMerge | undefined; - let rootChangeTaskId: string | undefined; - syncB.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - rootResult = syncResult as SyncResultFastForwardMerge; - rootChangeTaskId = taskMetadata.taskId; - }, - '' - ); - - let complete = false; - let endTaskId = ''; - let completeCollectionPath: string | undefined; - syncB.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - completeCollectionPath = taskMetadata.collectionPath; - }); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(col01Result?.action).toBe('fast-forward merge'); - expect(rootResult?.action).toBe('fast-forward merge'); - - expect(col01Result?.commits).toMatchObject({ - local: getCommitInfo([putResult1, putResult2]), - }); - expect(rootResult?.commits).toMatchObject({ - local: getCommitInfo([putResult1, putResult2]), - }); - - expect(col01Result?.changes.local).toEqual([ - getChangedFileInsert(jsonA1, putResult1), - ]); - expect(changedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); - - expect(rootResult?.changes.local).toEqual([ - getChangedFileInsert(jsonA1dash, putResult1dash), - getChangedFileInsert(jsonA2dash, putResult2dash), - ]); - - expect(col01ChangeTaskId).toBe(endTaskId); - expect(rootChangeTaskId).toBe(endTaskId); - - expect(completeCollectionPath).toBe(''); - - await destroyDBs([dbA, dbB]); - }); - - it('occurs change events with update and delete', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const col01 = dbA.collection('col01'); - const col02 = dbA.collection('col02'); - const jsonA1 = { _id: '1', name: 'fromA' }; - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult1 = await col01.put(jsonA1); - await col02.put(jsonA2); - await syncA.trySync(); - const jsonA1updated = { _id: '1', name: 'updated' }; - const putResult1updated = await col01.put(jsonA1updated); - const deleteResult2 = await col02.delete(jsonA2); - - let col01Result: SyncResultPush | undefined; - let col01ChangeTaskId: string | undefined; - syncA.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - col01Result = syncResult as SyncResultPush; - col01ChangeTaskId = taskMetadata.taskId; - }, - 'col01' - ); - - let changedFiles: ChangedFile[]; - syncA.on( - 'remoteChange', - (files: ChangedFile[], taskMetadata: TaskMetadata) => { - changedFiles = files; - }, - 'col02' - ); - - let complete = false; - syncA.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - }); - await syncA.tryPush(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(col01Result?.action).toBe('push'); - - expect(col01Result?.commits).toMatchObject({ - remote: getCommitInfo([putResult1updated, deleteResult2]), - }); - - expect(col01Result?.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResult1, jsonA1updated, putResult1updated), - ]); - expect(changedFiles!).toEqual([getChangedFileDelete(jsonA2, deleteResult2)]); - - await destroyDBs([dbA, dbB]); - }); - - it('occurs change and remoteChange events by trySync', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const col01 = dbA.collection('col01'); - const col02 = dbA.collection('col02'); - const jsonA1 = { _id: '1', name: 'fromA' }; - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult1 = await col01.put(jsonA1); - const putResult2 = await col02.put(jsonA2); - - const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; - const putResult1dash = { ...putResult1, _id: 'col01/1' }; - const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; - const putResult2dash = { ...putResult2, _id: 'col02/2' }; - - let col01Result: SyncResultPush | undefined; - let col01ChangeTaskId: string | undefined; - syncA.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - col01Result = syncResult as SyncResultPush; - col01ChangeTaskId = taskMetadata.taskId; - }, - 'col01' - ); - - let changedFiles: ChangedFile[]; - syncA.on( - 'remoteChange', - (files: ChangedFile[], taskMetadata: TaskMetadata) => { - changedFiles = files; - }, - 'col02' - ); - - let rootResult: SyncResultPush | undefined; - let rootChangeTaskId: string | undefined; - syncA.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - rootResult = syncResult as SyncResultPush; - rootChangeTaskId = taskMetadata.taskId; - }, - '' - ); - - let complete = false; - let endTaskId = ''; - let completeCollectionPath: string | undefined; - syncA.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - completeCollectionPath = taskMetadata.collectionPath; - }); - await syncA.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(col01Result?.action).toBe('push'); - expect(rootResult?.action).toBe('push'); - - expect(col01Result?.commits).toMatchObject({ - remote: getCommitInfo([putResult1, putResult2]), - }); - expect(rootResult?.commits).toMatchObject({ - remote: getCommitInfo([putResult1, putResult2]), - }); - - expect(col01Result?.changes.remote).toEqual([ - getChangedFileInsert(jsonA1, putResult1), - ]); - expect(changedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); - - expect(rootResult?.changes.remote).toEqual([ - getChangedFileInsert(jsonA1dash, putResult1dash), - getChangedFileInsert(jsonA2dash, putResult2dash), - ]); - - expect(col01ChangeTaskId).toBe(endTaskId); - expect(rootChangeTaskId).toBe(endTaskId); - - expect(completeCollectionPath).toBe(''); - - await destroyDBs([dbA, dbB]); - }); - - it('occurs change and remoteChange events by tryPush', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const col01 = dbA.collection('col01'); - const col02 = dbA.collection('col02'); - const jsonA1 = { _id: '1', name: 'fromA' }; - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult1 = await col01.put(jsonA1); - const putResult2 = await col02.put(jsonA2); - - const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; - const putResult1dash = { ...putResult1, _id: 'col01/1' }; - const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; - const putResult2dash = { ...putResult2, _id: 'col02/2' }; - - let col01Result: SyncResultPush | undefined; - let col01ChangeTaskId: string | undefined; - syncA.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - col01Result = syncResult as SyncResultPush; - col01ChangeTaskId = taskMetadata.taskId; - }, - 'col01' - ); - - let changedFiles: ChangedFile[]; - syncA.on( - 'remoteChange', - (files: ChangedFile[], taskMetadata: TaskMetadata) => { - changedFiles = files; - }, - 'col02' - ); - - let rootResult: SyncResultPush | undefined; - let rootChangeTaskId: string | undefined; - syncA.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - rootResult = syncResult as SyncResultPush; - rootChangeTaskId = taskMetadata.taskId; - }, - '' - ); - - let complete = false; - let endTaskId = ''; - let completeCollectionPath: string | undefined; - syncA.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - completeCollectionPath = taskMetadata.collectionPath; - }); - await syncA.tryPush(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(col01Result?.action).toBe('push'); - expect(rootResult?.action).toBe('push'); - - expect(col01Result?.commits).toMatchObject({ - remote: getCommitInfo([putResult1, putResult2]), - }); - expect(rootResult?.commits).toMatchObject({ - remote: getCommitInfo([putResult1, putResult2]), - }); - - expect(col01Result?.changes.remote).toEqual([ - getChangedFileInsert(jsonA1, putResult1), - ]); - expect(changedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); - - expect(rootResult?.changes.remote).toEqual([ - getChangedFileInsert(jsonA1dash, putResult1dash), - getChangedFileInsert(jsonA2dash, putResult2dash), - ]); - - expect(col01ChangeTaskId).toBe(endTaskId); - expect(rootChangeTaskId).toBe(endTaskId); - - expect(completeCollectionPath).toBe(''); - - await destroyDBs([dbA, dbB]); - }); - - it('occurs change, localChange, and remoteChange events by merge and push', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const col01 = dbA.collection('col01'); - const col02 = dbA.collection('col02'); - const jsonA1 = { _id: '1', name: 'fromA' }; - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult1 = await col01.put(jsonA1); - const putResult2 = await col02.put(jsonA2); - - const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; - const putResult1dash = { ...putResult1, _id: 'col01/1' }; - const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; - const putResult2dash = { ...putResult2, _id: 'col02/2' }; - - const jsonB3 = { _id: '3', name: 'fromB' }; - const putResult3 = await dbB.collection('col01').put(jsonB3); - const jsonB3dash = { _id: 'col01/3', name: 'fromB' }; - const putResult3dash = { ...putResult3, _id: 'col01/3' }; - await syncB.trySync(); - - let col01Result: SyncResultMergeAndPush | undefined; - let col01ChangeTaskId: string | undefined; - syncA.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - col01Result = syncResult as SyncResultMergeAndPush; - col01ChangeTaskId = taskMetadata.taskId; - }, - 'col01' - ); - - let localChangedFiles: ChangedFile[]; - syncA.on( - 'localChange', - (files: ChangedFile[], taskMetadata: TaskMetadata) => { - localChangedFiles = files; - }, - 'col01' - ); - - let remoteChangedFiles: ChangedFile[]; - syncA.on( - 'remoteChange', - (files: ChangedFile[], taskMetadata: TaskMetadata) => { - remoteChangedFiles = files; - }, - 'col02' - ); - - let rootResult: SyncResultMergeAndPush | undefined; - let rootChangeTaskId: string | undefined; - syncA.on( - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - rootResult = syncResult as SyncResultMergeAndPush; - rootChangeTaskId = taskMetadata.taskId; - }, - '' - ); - - let complete = false; - let endTaskId = ''; - let completeCollectionPath: string | undefined; - syncA.on( - 'complete', - (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - completeCollectionPath = taskMetadata.collectionPath; - }, - 'col01' - ); - await syncA.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(col01Result?.action).toBe('merge and push'); - expect(rootResult?.action).toBe('merge and push'); - - expect(col01Result?.commits).toMatchObject({ - remote: getCommitInfo([putResult1, putResult2, 'merge']), - local: getCommitInfo([putResult3, 'merge']), - }); - expect(rootResult?.commits).toMatchObject({ - remote: getCommitInfo([putResult1, putResult2, 'merge']), - local: getCommitInfo([putResult3, 'merge']), - }); - - expect(col01Result?.changes.remote).toEqual([ - getChangedFileInsert(jsonA1, putResult1), - ]); - expect(col01Result?.changes.local).toEqual([ - getChangedFileInsert(jsonB3, putResult3), - ]); - expect(localChangedFiles!).toEqual([getChangedFileInsert(jsonB3, putResult3)]); - expect(remoteChangedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); - - expect(rootResult?.changes.remote).toEqual([ - getChangedFileInsert(jsonA1dash, putResult1dash), - getChangedFileInsert(jsonA2dash, putResult2dash), - ]); - expect(rootResult?.changes.local).toEqual([ - getChangedFileInsert(jsonB3dash, putResult3dash), - ]); - - expect(col01ChangeTaskId).toBe(endTaskId); - expect(rootChangeTaskId).toBe(endTaskId); - - expect(completeCollectionPath).toBe('col01/'); - - await destroyDBs([dbA, dbB]); - }); - }); - - it('pause and resume', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - interval: 3000, - } - ); - - let resume = false; - syncB.on('resume', () => { - resume = true; - }); - let pause = false; - syncB.on('pause', () => { - pause = true; - }); - let complete = false; - syncB.on('complete', () => { - complete = true; - }); - - // Check first complete event - - let sleepTime = 0; - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - sleepTime += 1000; - } - - syncB.pause(); - expect(pause).toBe(true); - expect(resume).toBe(false); - expect(syncB.options.live).toBe(false); - - // Check second complete event - complete = false; // reset - // fast forward timer - await sleep(sleepTime + 1000); - - expect(complete).toBe(false); // complete will not happen because synchronization is paused. - - syncB.resume(); - expect(resume).toBe(true); - expect(syncB.options.live).toBe(true); - - // Check third complete event - complete = false; // reset - // fast forward timer - await sleep(sleepTime + 1000); - - expect(complete).toBe(true); - - await destroyDBs([dbA, dbB]); - }); - - it('active at initialization', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - }; - await dbA.open(); - - const repos = dbA.repository(); - const sync = new Sync(dbA, options); - let resume = false; - sync.on('resume', () => { - resume = true; - }); - - const syncResult = await sync.init(repos!); - console.log(JSON.stringify(syncResult)); - expect(resume).toBe(true); - - sync.close(); - - await destroyDBs([dbA]); - }); - - it('starts once', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - interval: 3000, - }); - - let start = false; - syncA.on('start', () => { - start = true; - }); - - expect(start).toBe(false); - - let sleepTime = 0; - // eslint-disable-next-line no-unmodified-loop-condition - while (!start) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - sleepTime += 1000; - } - - expect(start).toBe(true); - expect(sleepTime).toBeLessThan(5000); - - await destroyDBs([dbA]); - }); - - it('starts repeatedly', async () => { - const interval = MINIMUM_SYNC_INTERVAL; - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - interval, - }); - - let counter = 0; - syncA.on('start', () => { - counter++; - }); - - await sleep(interval * 5); - - expect(counter).toBeGreaterThanOrEqual(3); - - await destroyDBs([dbA]); - }); - - it('starts event returns taskMetaData and current retries', async () => { - const interval = MINIMUM_SYNC_INTERVAL; - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - interval, - }); - - let counter = 0; - let taskId = ''; - let currentRetries = -1; - syncA.on('start', (taskMetadata: TaskMetadata, _currentRetries: number) => { - counter++; - taskId = taskMetadata.taskId; - currentRetries = _currentRetries; - }); - - await sleep(interval * 5); - - expect(counter).toBeGreaterThanOrEqual(3); - expect(taskId).not.toBe(''); - expect(currentRetries).toBe(0); - - await destroyDBs([dbA]); - }); - - it('completes once', async () => { - const interval = MINIMUM_SYNC_INTERVAL; - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - interval, - }); - - let startTaskId = ''; - syncA.on('start', (taskMetadata: TaskMetadata) => { - startTaskId = taskMetadata.taskId; - }); - - let complete = false; - let endTaskId = ''; - syncA.on('complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - - expect(complete).toBe(false); - - let sleepTime = 0; - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - sleepTime += 1000; - } - - expect(complete).toBe(true); - expect(startTaskId).toBe(endTaskId); - expect(sleepTime).toBeLessThan(interval * 2); - - await destroyDBs([dbA]); - }); - - it('completes repeatedly', async () => { - const interval = MINIMUM_SYNC_INTERVAL; - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - interval, - }); - - let counter = 0; - syncA.on('complete', () => { - counter++; - }); - - await sleep(interval * 5); - - expect(counter).toBeGreaterThanOrEqual(3); - - await destroyDBs([dbA]); - }); - - it('error', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - await dbA.put({ _id: '1', name: 'fromA' }); - await syncA.trySync(); - - await destroyRemoteRepository(syncA.remoteURL); - // Create different repository with the same repository name. - const [dbB, syncB] = await createDatabase(remoteURLBase, localDir, serialId); - await dbB.put({ _id: '1', name: 'fromB' }); - await syncB.trySync(); - - let startTaskId = ''; - syncA.on('start', (taskMetadata: TaskMetadata) => { - startTaskId = taskMetadata.taskId; - }); - - let error = false; - let errorTaskId = ''; - syncA.on('error', (e: Error, taskMetadata: TaskMetadata) => { - error = true; - errorTaskId = taskMetadata.taskId; - }); - await expect(syncA.trySync()).rejects.toThrowError(Err.SyncWorkerError); - - expect(error).toBe(true); - expect(startTaskId).toBe(errorTaskId); - - error = false; - await expect(syncA.tryPush()).rejects.toThrowError(); // request failed with status code: 404 - - expect(error).toBe(true); - - await destroyDBs([dbA, dbB]); - }); - - it('on and off', async () => { - const interval = MINIMUM_SYNC_INTERVAL; - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - connection: { type: 'github', personalAccessToken: token }, - includeCommits: true, - live: true, - interval, - }); - - let counter = 0; - const increment = () => { - counter++; - }; - syncA.on('start', increment); - - await sleep(interval * 3); - - expect(counter).toBeGreaterThanOrEqual(1); - expect(counter).toBeLessThanOrEqual(3); - - syncA.off('start', increment); - - await sleep(interval * 3); - - expect(counter).toBeLessThanOrEqual(3); - - await destroyDBs([dbA]); - }); -}); diff --git a/test/remote/sync_trypush.test.ts b/test/remote/sync_trypush.test.ts deleted file mode 100644 index 18b4cfc8..00000000 --- a/test/remote/sync_trypush.test.ts +++ /dev/null @@ -1,398 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test push - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import { - compareWorkingDirAndBlobs, - createDatabase, - destroyDBs, - getChangedFileDelete, - getChangedFileInsert, - getChangedFileUpdate, - getCommitInfo, - getWorkingDirDocs, - removeRemoteRepositories, -} from '../remote_utils'; -import { SyncResultCancel, SyncResultPush } from '../../src/types'; -import { sleep } from '../../src/utils'; - -const reposPrefix = 'test_sync_trypush___'; -const localDir = `./test/database_sync_trypush`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak of getCommitLogs() - // fs.removeSync(path.resolve(localDir)); -}); - -// This test needs environment variables: -// - GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(': Sync#tryPush()', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - /** - * before: - * dbA : +jsonA1 - * after : jsonA1 - */ - it('changes one remote creation when pushes after one put()', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - // Put and push - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult = await dbA.put(jsonA1); - const syncResult = await syncA.tryPush(); - expect(syncResult.action).toBe('push'); - if (syncResult.action !== 'push') { - // Check discriminated union - return; - } - expect(syncResult.commits).toMatchObject({ - remote: getCommitInfo([putResult]), - }); - - // One remote creation - expect(syncResult.changes.remote.length).toBe(1); - expect(syncResult.changes.remote).toEqual([getChangedFileInsert(jsonA1, putResult)]); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * after : jsonA1 - */ - it('does not change remote when pushes after put() the same document again', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - - // This document is same as the previous document - // while put() creates a new commit. - // (This is valid behavior of put() API.) - const putResult = await dbA.put(jsonA1); - const syncResult = await syncA.tryPush(); - expect(syncResult.action).toBe('push'); - if (syncResult.action !== 'push') { - // Check discriminated union - return; - } - - expect(syncResult.commits).toMatchObject({ - remote: getCommitInfo([putResult]), - }); - - // Does not change remote - expect(syncResult.changes.remote.length).toBe(0); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * after : jsonA1 - */ - it('changes one remote update when pushes after put() updated document', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // Put and push an updated document - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResult = await dbA.put(jsonA1dash); - const syncResult = await syncA.tryPush(); - expect(syncResult.action).toBe('push'); - if (syncResult.action !== 'push') { - // Check discriminated union - return; - } - - expect(syncResult.commits).toMatchObject({ - remote: getCommitInfo([putResult]), - }); - - // One remote update - expect(syncResult.changes.remote.length).toBe(1); - expect(syncResult.changes.remote[0]).toMatchObject( - getChangedFileUpdate(jsonA1, putResultA1, jsonA1dash, putResult) - ); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA2 - * after : jsonA1 jsonA2 - */ - it('changes one remote creation when pushes after put() another document', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - - // Put and push another document - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - const syncResult = await syncA.tryPush(); - expect(syncResult.action).toBe('push'); - if (syncResult.action !== 'push') { - // Check discriminated union - return; - } - - expect(syncResult.commits).toMatchObject({ - remote: getCommitInfo([putResultA2]), - }); - - // One remote creation - expect(syncResult.changes.remote.length).toBe(1); - expect(syncResult.changes.remote[0]).toMatchObject( - getChangedFileInsert(jsonA2, putResultA2) - ); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: - * dbA : +jsonA1 +jsonA2 - * after1: jsonA1 jsonA2 - * dbA : +jsonA1 +jsonA3 - * after2: jsonA1 jsonA2 jsonA3 - */ - it('changes two remote creations when pushes after put() two documents', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - // Two put commands and push - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult2 = await dbA.put(jsonA2); - const syncResult = await syncA.tryPush(); - expect(syncResult.action).toBe('push'); - if (syncResult.action !== 'push') { - // Check discriminated union - return; - } - - expect(syncResult.commits).toMatchObject({ - remote: getCommitInfo([putResult1, putResult2]), - }); - - // Two remote creations - expect(syncResult.changes.remote.length).toBe(2); - expect(syncResult.changes.remote).toEqual([ - getChangedFileInsert(jsonA1, putResult1), - getChangedFileInsert(jsonA2, putResult2), - ]); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 jsonA2 - * after : +jsonA1 jsonA2 - */ - it('changes one remote creation and one remote update when pushes after put() updated document and another document', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResult1dash = await dbA.put(jsonA1dash); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult2 = await dbA.put(jsonA2); - const syncResult = await syncA.tryPush(); - expect(syncResult.action).toBe('push'); - if (syncResult.action !== 'push') { - // Check discriminated union - return; - } - - expect(syncResult.commits).toMatchObject({ - remote: getCommitInfo([putResult1dash, putResult2]), - }); - - // One remote update and one remote creation - expect(syncResult.changes.remote.length).toBe(2); - expect(syncResult.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResult1, jsonA1dash, putResult1dash), - getChangedFileInsert(jsonA2, putResult2), - ]); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash, jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: jsonA1 - * dbA : -jsonA1 - * after : - */ - it('changes one remote delete when pushes after one delete()', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - - const deleteResult1 = await dbA.delete(jsonA1); - - const syncResult1 = await syncA.tryPush(); - expect(syncResult1.action).toBe('push'); - if (syncResult1.action !== 'push') { - // Check discriminated union - return; - } - - expect(syncResult1.commits).toMatchObject({ - remote: getCommitInfo([deleteResult1]), - }); - - // One remote delete - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileDelete(jsonA1, deleteResult1), - ]); - - expect(getWorkingDirDocs(dbA)).toEqual([]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: - * dbA : +jsonA1 - * dbA : -jsonA1 - * after : - */ - it('does not change remote when pushes after put() and delete()', async function () { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - const jsonA1 = { _id: '1', name: 'fromA' }; - // Put and delete the same document - const putResult1 = await dbA.put(jsonA1); - const deleteResult1 = await dbA.delete(jsonA1); - - const syncResult1 = await syncA.tryPush(); - expect(syncResult1.action).toBe('push'); - if (syncResult1.action !== 'push') { - // Check discriminated union - return; - } - - expect(syncResult1.commits).toMatchObject({ - remote: getCommitInfo([putResult1, deleteResult1]), - }); - - // Does not change remote - expect(syncResult1.changes.remote.length).toBe(0); - - expect(getWorkingDirDocs(dbA)).toEqual([]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - it('skips consecutive push tasks', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - const results: (SyncResultPush | SyncResultCancel)[] = []; - for (let i = 0; i < 10; i++) { - // eslint-disable-next-line promise/catch-or-return - syncA.tryPush().then(result => results.push(result)); - } - await sleep(5000); - - const syncResultCancel: SyncResultCancel = { - action: 'canceled', - }; - // results will be include 7 or more cancels - let cancelCount = 0; - results.forEach(res => { - if (res.action === 'canceled') cancelCount++; - }); - expect(cancelCount).toBeGreaterThan(6); - - // 3 or less tryPushes will be executed - expect(dbA.taskQueue.currentStatistics().push).toBeLessThanOrEqual(3); - - await destroyDBs([dbA]); - }); -}); diff --git a/test/remote/sync_trysync.test.ts b/test/remote/sync_trysync.test.ts deleted file mode 100644 index 8c644cc8..00000000 --- a/test/remote/sync_trysync.test.ts +++ /dev/null @@ -1,738 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test sync - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import { GitDocumentDB } from '../../src/git_documentdb'; -import { - SyncResult, - SyncResultFastForwardMerge, - SyncResultMergeAndPush, - SyncResultPush, - SyncResultResolveConflictsAndPush, -} from '../../src/types'; -import { Err } from '../../src/error'; -import { - compareWorkingDirAndBlobs, - createClonedDatabases, - createDatabase, - destroyDBs, - getChangedFileDelete, - getChangedFileInsert, - getChangedFileUpdate, - getCommitInfo, - getWorkingDirDocs, - removeRemoteRepositories, -} from '../remote_utils'; -import { sleep } from '../../src/utils'; - -const reposPrefix = 'test_sync_trysync___'; -const localDir = `./test/database_sync_trysync`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak of getCommitLogs() - // fs.removeSync(path.resolve(localDir)); -}); - -// This test needs environment variables: -// - GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(': Sync#trySync()', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - /** - * before: - * dbA : - * after : - */ - it('returns SyncResultNop when no commit', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - const syncResult1 = (await syncA.trySync()) as SyncResultPush; - - expect(syncResult1.action).toBe('nop'); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - describe('returns SyncResultPush', () => { - /** - * before: - * dbA : jsonA1 - * after : jsonA1 - */ - it('which includes one remote creation when a local db creates a document', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const syncResult1 = (await syncA.trySync()) as SyncResultPush; - - expect(syncResult1.action).toBe('push'); - expect(syncResult1.commits!.remote.length).toBe(1); - expect(syncResult1.commits!.remote[0].oid).toBe(putResultA1.commit.oid); - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileInsert(jsonA1, putResultA1), - ]); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: jsonA1 - * dbA : -jsonA1 - * after : - */ - it('which includes one remote delete when a local db deletes a document', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const deleteResultA1 = await dbA.delete(jsonA1); - const syncResult1 = (await syncA.trySync()) as SyncResultPush; - - expect(syncResult1.action).toBe('push'); - expect(syncResult1.commits!.remote.length).toBe(1); - expect(syncResult1.commits!.remote[0].oid).toBe(deleteResultA1.commit.oid); - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileDelete(jsonA1, deleteResultA1), - ]); - - expect(getWorkingDirDocs(dbA)).toEqual([]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * after : jsonA1 - */ - it('which includes one remote update when a local db a document', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - const syncResult1 = (await syncA.trySync()) as SyncResultPush; - - expect(syncResult1.action).toBe('push'); - expect(syncResult1.commits!.remote.length).toBe(1); - expect(syncResult1.commits!.remote[0].oid).toBe(putResultA1dash.commit.oid); - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdate(jsonA1, putResultA1, jsonA1dash, putResultA1dash), - ]); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - - await destroyDBs([dbA]); - }); - }); - - describe('returns SyncResultFastForwardMerge', () => { - /** - * before: - * dbA : jsonA1 - * dbB : - * after : jsonA1 - */ - it('which includes one local creation when a remote db creates a document', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - - await syncA.tryPush(); - - // B syncs - const syncResult1 = (await syncB.trySync()) as SyncResultFastForwardMerge; - expect(syncResult1.action).toBe('fast-forward merge'); - expect(syncResult1.commits!.local.length).toBe(1); - expect(syncResult1.commits!.local[0].oid).toBe(putResult1.commit.oid); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); - - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: - * dbA : jsonA1 jsonA2 - * dbB : - * after : jsonA1 jsonA2 - */ - it('which includes two local creations when a remote db creates two documents', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - const putResult2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B syncs - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('fast-forward merge'); - expect(syncResult1.commits!.local.length).toBe(2); - expect(syncResult1.commits!.local[0].oid).toBe(putResult1.commit.oid); - expect(syncResult1.commits!.local[1].oid).toBe(putResult2.commit.oid); - expect(syncResult1.changes.local.length).toBe(2); - expect(syncResult1.changes.local).toEqual( - expect.arrayContaining([ - getChangedFileInsert(jsonA1, putResult1), - getChangedFileInsert(jsonA2, putResult2), - ]) - ); - - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonA2]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - }); - - describe('returns SyncResultMergeAndPush', () => { - /** - * before: - * dbA : jsonA1 - * dbB : jsonB2 - * after : jsonA1 jsonB2 - */ - it('which includes local and remote creations when a remote db creates a document and a local db creates another document', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B syncs - const jsonB2 = { _id: '2', name: 'fromB' }; - const putResultB2 = await dbB.put(jsonB2); - - // Sync dbB - const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; - expect(syncResult1.action).toBe('merge and push'); - - expect(syncResult1.commits!.local.length).toBe(2); // put commit and merge commit - expect(syncResult1.commits!.remote.length).toBe(2); // put commit and merge commit - expect(syncResult1.commits!.local[0].oid).toBe(putResultA1.commit.oid); - expect(syncResult1.commits!.local[1].message).toBe('merge'); - expect(syncResult1.commits!.remote[0].oid).toBe(putResultB2.commit.oid); - expect(syncResult1.commits!.remote[1].message).toBe('merge'); - - expect(syncResult1.changes.local).toEqual([ - getChangedFileInsert(jsonA1, putResultA1), - ]); - - expect(syncResult1.changes.remote).toEqual([ - getChangedFileInsert(jsonB2, putResultB2), - ]); - - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB2]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: - * dbA : jsonA1 jsonA2 - * dbB : jsonB3 jsonB4 - * after : jsonA1 jsonA2 jsonB3 jsonB4 - */ - it('which includes two local creations and two remote creations when a remote db creates two documents and a local db creates two different documents', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B syncs - const jsonB3 = { _id: '3', name: 'fromB' }; - const putResultB3 = await dbB.put(jsonB3); - const jsonB4 = { _id: '4', name: 'fromB' }; - const putResultB4 = await dbB.put(jsonB4); - - const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; - expect(syncResult1.action).toBe('merge and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([putResultA1, putResultA2, 'merge']), - remote: getCommitInfo([putResultB3, putResultB4, 'merge']), - }); - - expect(syncResult1.changes.local.length).toBe(2); - expect(syncResult1.changes.local).toEqual( - expect.arrayContaining([ - getChangedFileInsert(jsonA1, putResultA1), - getChangedFileInsert(jsonA2, putResultA2), - ]) - ); - - expect(syncResult1.changes.remote.length).toBe(2); - expect(syncResult1.changes.remote).toEqual( - expect.arrayContaining([ - getChangedFileInsert(jsonB3, putResultB3), - getChangedFileInsert(jsonB4, putResultB4), - ]) - ); - - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonA2, jsonB3, jsonB4]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2, jsonB3, jsonB4]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: - * dbA : jsonA1 - * dbB : jsonA1 - * after : jsonA1 - */ - it('which does not include changes after a remote db creates a document and a local db creates exactly the same document', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B puts the same file with exactly the same contents - const putResultB1 = await dbB.put(jsonA1); - - const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; - expect(syncResult1.action).toBe('merge and push'); - - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([putResultA1, 'merge']), - remote: getCommitInfo([putResultB1, 'merge']), - }); - - expect(syncResult1.changes.local.length).toBe(0); - expect(syncResult1.changes.remote.length).toBe(0); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : +jsonA1 - * after : jsonA1 - */ - it('which does not include changes after a remote db updates a document and a local db updates exactly the same update', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // Clone - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A updates and pushes - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B updates the same file with exactly the same contents - const putResultB1dash = await dbB.put(jsonA1dash); - - const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; - expect(syncResult1.action).toBe('merge and push'); - - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([putResultA1dash, 'merge']), - remote: getCommitInfo([putResultB1dash, 'merge']), - }); - - expect(syncResult1.changes.local.length).toBe(0); - expect(syncResult1.changes.remote.length).toBe(0); - - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : jsonA2 - * dbB : -jsonA1 - * after : jsonA2 - */ - it('which include a local create and a remote delete when a remote db creates a document and a local db deletes another document', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A puts and pushes - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B deletes and syncs - const deleteResultB1 = await dbB.delete(jsonA1); - - const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; - expect(syncResult1.action).toBe('merge and push'); - - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([putResultA2, 'merge']), - remote: getCommitInfo([deleteResultB1, 'merge']), - }); - - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileInsert(jsonA2, putResultA2), - ]); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileDelete(jsonA1, deleteResultB1), - ]); - - expect(getWorkingDirDocs(dbB)).toEqual([jsonA2]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : -jsonA1 - * dbB : jsonB2 - * after : jsonB2 - */ - it('which include a remote create and a local delete when a remote db deletes a document and a local db creates another document', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A deletes and pushes - const deleteResultA1 = await dbA.delete(jsonA1); - await syncA.tryPush(); - - // B put another file and syncs - const jsonB2 = { _id: '2', name: 'fromB' }; - const putResultB2 = await dbB.put(jsonB2); - - const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; - expect(syncResult1.action).toBe('merge and push'); - - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([deleteResultA1, 'merge']), - remote: getCommitInfo([putResultB2, 'merge']), - }); - - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileDelete(jsonA1, deleteResultA1), - ]); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileInsert(jsonB2, putResultB2), - ]); - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB2]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : -jsonA1 - * dbB : -jsonA1 - * after : - */ - it('which does not include changes when a remote db deletes a document and a local db deletes the same document', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A deletes and pushes - const deleteResultA1 = await dbA.delete(jsonA1); - await syncA.tryPush(); - - // B deletes the same file and syncs - const deleteResultB1 = await dbB.delete(jsonA1); - - const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; - expect(syncResult1.action).toBe('merge and push'); - - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([deleteResultA1, 'merge']), - remote: getCommitInfo([deleteResultB1, 'merge']), - }); - - expect(syncResult1.changes.local.length).toBe(0); // Must no be 1 but 0, because diff is empty. - expect(syncResult1.changes.remote.length).toBe(0); // Must no be 1 but 0, because diff is empty. - - expect(getWorkingDirDocs(dbB)).toEqual([]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - }); - - it('skips consecutive sync tasks', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - const results: SyncResult[] = []; - for (let i = 0; i < 3; i++) { - // eslint-disable-next-line promise/catch-or-return - syncA.trySync().then(result => results.push(result)); - } - await sleep(5000); - - // results will be include 9 cancels - let cancelCount = 0; - results.forEach(res => { - if (res.action === 'canceled') cancelCount++; - }); - // Check results - expect(cancelCount).toBeGreaterThanOrEqual(1); - - // Check statistics - expect(dbA.taskQueue.currentStatistics().cancel).toBeGreaterThanOrEqual(1); - - // Only one trySync() will be executed - expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThanOrEqual(1); - - await destroyDBs([dbA]); - }); - - it('skips consecutive sync tasks after crud tasks', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - const jsonA1 = { _id: '1', name: 'fromA' }; - for (let i = 0; i < 10; i++) { - dbA.put(jsonA1); - } - const results: SyncResult[] = []; - for (let i = 0; i < 3; i++) { - // eslint-disable-next-line promise/catch-or-return - syncA.trySync().then(result => results.push(result)); - } - await sleep(10000); - - // results will be include 9 cancels - let cancelCount = 0; - results.forEach(res => { - if (res.action === 'canceled') cancelCount++; - }); - // Check results - expect(cancelCount).toBeGreaterThanOrEqual(1); - - // Check statistics - expect(dbA.taskQueue.currentStatistics().cancel).toBeGreaterThanOrEqual(1); - - // Only one trySync() will be executed - expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThanOrEqual(1); - - await destroyDBs([dbA]); - }); - - it('throws UnfetchedCommitExistError for [push] direction', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - syncDirection: 'push', - }); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir, - }); - await dbB.open(); - - // tryPush throws UnfetchedCommitExistsError - await expect(dbB.sync(syncA.options)).rejects.toThrowError( - Err.UnfetchedCommitExistsError - ); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); -}); diff --git a/test/remote_base/3way_merge.ts b/test/remote_base/3way_merge.ts new file mode 100644 index 00000000..65790394 --- /dev/null +++ b/test/remote_base/3way_merge.ts @@ -0,0 +1,1975 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test 3-way merge + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import expect from 'expect'; +import { Err } from '../../src/error'; +import { threeWayMerge } from '../../src/remote/3way_merge'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { + ConnectionSettings, + FatDoc, + JsonDoc, + SyncResultMergeAndPush, + SyncResultResolveConflictsAndPush, +} from '../../src/types'; +import { + compareWorkingDirAndBlobs, + createClonedDatabases, + createDatabase, + destroyDBs, + getChangedFileDelete, + getChangedFileInsert, + getChangedFileUpdate, + getCommitInfo, + getWorkingDirDocs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { JSON_POSTFIX, YAML_POSTFIX } from '../../src/const'; + +export const syncThreeWayMergeBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe('', () => { + it('throws InvalidConflictsStateError', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + + await expect( + // @ts-ignore + threeWayMerge(dbA, syncA, 'ours-diff', 'foo', undefined, undefined, undefined) + ).rejects.toThrowError(Err.InvalidConflictStateError); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: + * dbA : jsonA1 jsonA2 + * dbB : jsonB1 jsonB3 + * after : jsonB1 jsonA2 jsonB3 + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2: 1 - Accept theirs (insert) + * jsonB3: 2 - Accept ours (insert) + */ + it('resolves case 1 - Accept theirs (insert), case 2 - Accept ours (insert), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B puts a new file + const jsonB3 = { _id: '3', name: 'fromB' }; + const putResultB3 = await dbB.put(jsonB3); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + putResultA2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + putResultB3, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA2, putResultA2), + ]); + + expect(syncResult1.changes.remote.length).toBe(2); + expect(syncResult1.changes.remote).toEqual( + expect.arrayContaining([ + getChangedFileInsert(jsonB3, putResultB3), + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + ]) + ); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2, jsonB3]); + // Sync dbA + await syncA.trySync(); + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2, jsonB3]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: + * dbA : jsonA1 jsonA2 + * dbB : jsonB1 jsonA2 + * after : jsonB1 jsonA2 + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2: 3 - Accept both (insert) + */ + it('resolves case 3 - Accept both (insert), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B puts the same file with the same contents + const putResultB2 = await dbB.put(jsonA2); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + putResultA2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + putResultB2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: + * dbA : jsonA1 + * dbB : jsonB1 + * after : jsonA1 + * + * 3-way merge: + * jsonA1: 5 - Conflict. Accept theirs (insert) + */ + it('resolves case 5 - Conflict. Accept theirs (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'theirs', + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + `resolve: 1${JSON_POSTFIX}(insert,${putResultA1.fileOid.substr(0, 7)},theirs)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(insert,${putResultA1.fileOid.substr(0, 7)},theirs)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdate(jsonB1, putResultB1, jsonA1, putResultA1), + ]); + + expect(syncResult1.changes.remote.length).toBe(0); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultA1.fileOid, + type: 'json', + doc: jsonA1, + }, + strategy: 'theirs', + operation: 'insert', + }, + ]); + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA2 + * dbA : jsonA1 -jsonA2 + * dbB : jsonB1 -jsonA2 + * after : jsonB1 + * + * '-' means delete + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2: 6 - Accept both (delete) + */ + it('resolves case 6 - Accept both (delete), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA2 = { _id: '2', name: 'fromA' }; + await dbA.put(jsonA2); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts, deletes, and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + + const deleteResultA2 = await dbA.delete(jsonA2); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B deletes the same file + const deleteResultB2 = await dbB.delete(jsonA2); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + deleteResultA2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + deleteResultB2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA2 + * dbA : jsonA1 + * dbB : jsonB1 -jsonA2 + * after : jsonB1 + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2: 7 - Accept ours (delete) + */ + it('resolves case 7 - Accept ours (delete), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA2 = { _id: '2', name: 'fromA' }; + await dbA.put(jsonA2); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B deletes the same file + const deleteResultB2 = await dbB.delete(jsonA2); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + deleteResultB2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(2); + expect(syncResult1.changes.remote).toEqual( + expect.arrayContaining([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + getChangedFileDelete(jsonA2, deleteResultB2), + ]) + ); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : -jsonA1 + * result: + * + * '+' means update + * + * 3-way merge: + * jsonA1: 8 - Conflict. Accept ours (delete) + */ + it('resolves case 8 - Conflict. Accept ours (delete)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A updates and pushes + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B deletes and syncs + const deleteResultB1 = await dbB.delete(jsonA1); + + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + deleteResultB1, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileDelete(jsonA1dash, putResultA1dash), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: deleteResultB1.fileOid, + type: 'json', + doc: jsonA1, + }, + strategy: 'ours', + operation: 'delete', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : -jsonA1 + * result: jsonA1 + * + * '+' means update + * + * 3-way merge: + * jsonA1: 9 - Conflict. Accept theirs (update) + */ + it('resolves case 9 - Conflict. Accept ours (delete)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'theirs', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A updates and pushes + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B deletes and syncs + const deleteResultB1 = await dbB.delete(jsonA1); + + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(update,${putResultA1dash.fileOid.substr( + 0, + 7 + )},theirs)`, + ]), + remote: getCommitInfo([ + deleteResultB1, + `resolve: 1${JSON_POSTFIX}(update,${putResultA1dash.fileOid.substr( + 0, + 7 + )},theirs)`, + ]), + }); + + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA1dash, putResultA1dash), + ]); + + expect(syncResult1.changes.remote.length).toBe(0); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultA1dash.fileOid, + type: 'json', + doc: jsonA1dash, + }, + strategy: 'theirs', + operation: 'update', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA2 + * dbA : jsonA1 -jsonA2 + * dbB : jsonB1 + * after : jsonB1 + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2:10 - Accept theirs (delete) + */ + it('resolves case 10 - Accept theirs (delete), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA2 = { _id: '2', name: 'fromA' }; + await dbA.put(jsonA2); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts, deletes, and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const deleteResultA2 = await dbA.delete(jsonA2); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + deleteResultA2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileDelete(jsonA2, deleteResultA2), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : -jsonA1 jsonA2 + * dbB : jsonB1 + * result: jsonB1 jsonA2 + * + * 3-way merge: + * jsonB1: 11 - Conflict. Accept ours (update) + * jsonA2: 1 - Accept theirs (insert) + */ + it('resolves case 11 - Conflict. Accept ours (update), case 1 - Accept theirs (insert), ', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A deletes the old file and puts a new file + const deleteResultA1 = await dbA.delete(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B updates the old file and syncs + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + deleteResultA1, + putResultA2, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA2, putResultA2), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileInsert(jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'update', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : -jsonA1 jsonA2 + * dbB : jsonB1 + * result: jsonA2 + * + * 3-way merge: + * jsonA1: 11 - Conflict. Accept theirs (delete) + * jsonA2: 1 - Accept theirs (insert) + */ + it('resolves case 12 - accept theirs (delete), case 1 - Accept theirs (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'theirs', + }); + + // A deletes the old file and puts a new file + const deleteResultA1 = await dbA.delete(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B updates the old file and syncs + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + deleteResultA1, + putResultA2, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultA1.fileOid.substr(0, 7)},theirs)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultA1.fileOid.substr(0, 7)},theirs)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(2); + expect(syncResult1.changes.local).toEqual( + expect.arrayContaining([ + getChangedFileDelete(jsonB1, putResultB1), + getChangedFileInsert(jsonA2, putResultA2), + ]) + ); + + expect(syncResult1.changes.remote.length).toBe(0); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: deleteResultA1.fileOid, + type: 'json', + doc: jsonA1, + }, + strategy: 'theirs', + operation: 'delete', + }, + ]); + // Conflict occurs on 1.json + expect(getWorkingDirDocs(dbA)).toEqual([jsonA2]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA2 + * dbA : jsonA1 +jsonA2 + * dbB : jsonB1 +jsonA2 + * after : jsonB1 +jsonA2 + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2:13 - Accept both (update) + */ + it('resolves case 13 - Accept both (update), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2dash = { _id: '2', name: 'updated' }; + const putResultA2dash = await dbA.put(jsonA2dash); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B puts the same file with the same contents + const putResultB2 = await dbB.put(jsonA2dash); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + putResultA2dash, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + putResultB2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2dash]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + // case 14 + /** + * before: jsonA2 + * dbA : jsonA1 +jsonA2 + * dbB : jsonB1 jsonA2 + * after : jsonB1 +jsonA2 + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2:14 - Accept theirs (update) + */ + it('resolves case 14 - Accept theirs (update), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2dash = { _id: '2', name: 'updated' }; + const putResultA2dash = await dbA.put(jsonA2dash); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B puts the same file with the previous contents + const putResultB2 = await dbB.put(jsonA2); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + putResultA2dash, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + putResultB2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdate(jsonA2, putResultB2, jsonA2dash, putResultA2dash), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2dash]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA2 + * dbA : jsonA1 jsonA2 + * dbB : jsonB1 jsonB2 + * after : jsonB1 jsonB2 + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2:15 - Accept ours (update) + */ + it('resolves case 15 - Accept ours (update), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + // A puts the previous file and pushes + const putResultA2dash = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B puts + const jsonB2 = { _id: '2', name: 'fromB' }; + const putResultB2 = await dbB.put(jsonB2); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + putResultA2dash, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + putResultB2, + `resolve: 1${JSON_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(2); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + getChangedFileUpdate(jsonA2, putResultA2dash, jsonB2, putResultB2), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonB2]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : jsonB1 + * + * 3-way merge: + * jsonB1:16 - Conflict. Accept ours (update) + */ + it('resolves case 16 - Conflict. Accept ours (update)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1dash, putResultA1dash, jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'update', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : +jsonA1 + * + * 3-way merge: + * jsonA1:17 - Conflict. Accept theirs (update) + */ + it('resolves case 17 - Conflict. Accept theirs (update)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'theirs', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'theirs', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(update,${putResultA1dash.fileOid.substr( + 0, + 7 + )},theirs)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(update,${putResultA1dash.fileOid.substr( + 0, + 7 + )},theirs)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdate(jsonB1, putResultB1, jsonA1dash, putResultA1dash), + ]); + + expect(syncResult1.changes.remote.length).toBe(0); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultA1dash.fileOid, + type: 'json', + doc: jsonA1dash, + }, + strategy: 'theirs', + operation: 'update', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 jsonA2 jsonA3 + * dbA : +jsonA1 -jsonA2 +jsonA3 + * dbB : -jsonA1 +jsonB2 +jsonB3 + * result: jsonB2 jsonB3 + * + * 3-way merge: + * jsonA1: 8 - Conflict. Accept ours (delete) + * jsonB2: 4 - Conflict. Accept ours (insert) + * jsonB3:11 - Conflict. Accept ours (update) + */ + it('resolves many conflicts', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + const jsonA3 = { _id: '3', name: 'fromA' }; + const putResultA3 = await dbA.put(jsonA3); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A updates, deletes, updates, and pushes + + // change commit order for test + // 3 -> 1 -> 2 + const jsonA3dash = { _id: '3', name: 'updated' }; + const putResultA3dash = await dbA.put(jsonA3dash); + + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + + const deleteResultA2 = await dbA.delete(jsonA2); + + await syncA.tryPush(); + + // B deletes, updates, updates, and syncs + + // change commit order for test + // 3 -> 1 -> 2 + const jsonB3 = { _id: '3', name: 'fromB' }; + const putResultB3 = await dbB.put(jsonB3); + + const deleteResultB1 = await dbB.delete(jsonA1); + + const jsonB2 = { _id: '2', name: 'fromB' }; + const putResultB2 = await dbB.put(jsonB2); + + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA3dash, + putResultA1dash, + deleteResultA2, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultB1.fileOid.substr( + 0, + 7 + )},ours), 2${JSON_POSTFIX}(update,${putResultB2.fileOid.substr( + 0, + 7 + )},ours), 3${JSON_POSTFIX}(update,${putResultB3.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB3, + deleteResultB1, + putResultB2, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultB1.fileOid.substr( + 0, + 7 + )},ours), 2${JSON_POSTFIX}(update,${putResultB2.fileOid.substr( + 0, + 7 + )},ours), 3${JSON_POSTFIX}(update,${putResultB3.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(3); + expect(syncResult1.changes.remote).toEqual( + expect.arrayContaining([ + getChangedFileDelete(jsonA1dash, putResultA1dash), + getChangedFileInsert(jsonB2, putResultB2), + getChangedFileUpdate(jsonA3dash, putResultA3dash, jsonB3, putResultB3), + ]) + ); + + expect(syncResult1.conflicts).toEqual( + expect.arrayContaining([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: deleteResultB1.fileOid, + type: 'json', + doc: jsonA1, + }, + strategy: 'ours', + operation: 'delete', + }, + { + fatDoc: { + _id: '2', + name: '2.json', + fileOid: putResultB2.fileOid, + type: 'json', + doc: jsonB2, + }, + strategy: 'ours', + operation: 'update', + }, + { + fatDoc: { + _id: '3', + name: '3.json', + fileOid: putResultB3.fileOid, + type: 'json', + doc: jsonB3, + }, + strategy: 'ours', + operation: 'update', + }, + ]) + ); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB2, jsonB3]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB2, jsonB3]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : jsonB1 + * + * 3-way merge: + * jsonB1:16 - Conflict. Accept ours (update) + */ + it('resolves case 16 by user strategy function.', async () => { + const userStrategyByDate = (ours?: FatDoc, theirs?: FatDoc) => { + if (ours === undefined || theirs === undefined) { + throw new Error('Undefined document'); + } + if ((ours.doc as JsonDoc).date > (theirs.doc as JsonDoc).date) { + return 'ours'; + } + return 'theirs'; + }; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: userStrategyByDate, + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'updated', date: '2021/05/16' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'fromB', date: '2021/06/16' }; + const putResultB1 = await dbB.put(jsonB1); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1dash, putResultA1dash, jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'update', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : +jsonA1 + * + * 3-way merge: + * jsonA1:17 - Conflict. Accept theirs (update) + */ + it('resolves case 17 by user strategy function.', async () => { + const userStrategyByDate = (ours?: FatDoc, theirs?: FatDoc) => { + if (ours === undefined || theirs === undefined) { + throw new Error('Undefined document'); + } + if ((ours.doc as JsonDoc).date > (theirs.doc as JsonDoc).date) { + return 'ours'; + } + return 'theirs'; + }; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: userStrategyByDate, + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'theirs', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'updated', date: '2021/06/16' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'fromB', date: '2021/05/16' }; + const putResultB1 = await dbB.put(jsonB1); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(update,${putResultA1dash.fileOid.substr( + 0, + 7 + )},theirs)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(update,${putResultA1dash.fileOid.substr( + 0, + 7 + )},theirs)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdate(jsonB1, putResultB1, jsonA1dash, putResultA1dash), + ]); + + expect(syncResult1.changes.remote.length).toBe(0); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultA1dash.fileOid, + type: 'json', + doc: jsonA1dash, + }, + strategy: 'theirs', + operation: 'update', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe('with front-matter', () => { + /** + * before: + * dbA : jsonA1 jsonA2.yml + * dbB : jsonB1 jsonB2.md + * after : jsonB1 jsonA2.yml jsonB2.md + * + * 3-way merge: + * jsonB1: 4 - Conflict. Accept ours (insert) + * jsonA2: 1 - Accept theirs (insert) + * jsonB2: 2 - Accept ours (insert) + */ + it('files have the same name but different extension: resolves case 1 - Accept theirs (insert), case 2 - Accept ours (insert), case 4 - Conflict. Accept ours (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + }, + 'info', + 'front-matter' + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; // 2.yml + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + // B puts a new file + const jsonB2 = { _id: '2', name: 'fromB', _body: 'bodyFromB' }; // 2.md + const putResultB2 = await dbB.put(jsonB2); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + putResultA2, + `resolve: 1${YAML_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + remote: getCommitInfo([ + putResultB1, + putResultB2, + `resolve: 1${YAML_POSTFIX}(insert,${putResultB1.fileOid.substr(0, 7)},ours)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA2, putResultA2, dbA.serializeFormat), + ]); + + expect(syncResult1.changes.remote.length).toBe(2); + expect(syncResult1.changes.remote).toEqual( + expect.arrayContaining([ + getChangedFileInsert(jsonB2, putResultB2, dbB.serializeFormat), + getChangedFileUpdate( + jsonA1, + putResultA1, + jsonB1, + putResultB1, + dbA.serializeFormat + ), + ]) + ); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.yml', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours', + operation: 'insert', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB, dbB.serializeFormat)).toEqual([jsonB1, jsonB2, jsonA2]); + // Sync dbA + await syncA.trySync(); + expect(getWorkingDirDocs(dbA, dbA.serializeFormat)).toEqual([jsonB1, jsonB2, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + }); +}; diff --git a/test/remote_base/3way_merge_ot.ts b/test/remote_base/3way_merge_ot.ts new file mode 100644 index 00000000..5a3c2535 --- /dev/null +++ b/test/remote_base/3way_merge_ot.ts @@ -0,0 +1,1059 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test Operational Transformation in 3-way merge + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import expect from 'expect'; +import { SerializeFormatFrontMatter } from '../../src/serialize_format'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { + ConnectionSettings, + RemoteOptions, + Schema, + SyncResultMergeAndPush, + SyncResultResolveConflictsAndPush, +} from '../../src/types'; +import { + compareWorkingDirAndBlobs, + createClonedDatabases, + createDatabase, + destroyDBs, + getChangedFileDelete, + getChangedFileInsert, + getChangedFileUpdateBySHA, + getCommitInfo, + getWorkingDirDocs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; + +import { FRONT_MATTER_POSTFIX, JSON_POSTFIX, YAML_POSTFIX } from '../../src/const'; + +export const threeWayMergeOtBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe('', () => { + /** + * before: + * dbA : jsonA1 jsonA2 + * dbB : jsonB1 jsonB3 + * after : mergedJson jsonA2 jsonB3 + * + * 3-way merge: + * mergedJson: 4 - Conflict. Accept ours (insert-merge) + * jsonA2: 1 - Accept theirs (insert) + * jsonB3: 2 - Accept ours (insert) + */ + it('resolves case 1 - Accept theirs (insert), case 2 - Accept ours (insert), case 4 - Conflict. Accept ours (insert-merge)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours-diff', + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA', a: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB', b: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + const mergedJson = { _id: '1', name: 'fromB', a: 'fromA', b: 'fromB' }; + + // B puts a new file + const jsonB3 = { _id: '3', name: 'fromB' }; + const putResultB3 = await dbB.put(jsonB3); + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.json'); + + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + putResultA2, + `resolve: 1${JSON_POSTFIX}(insert-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},ours-diff)`, + ]), + remote: getCommitInfo([ + putResultB1, + putResultB3, + `resolve: 1${JSON_POSTFIX}(insert-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},ours-diff)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(2); + expect(syncResult1.changes.local).toEqual( + expect.arrayContaining([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + getChangedFileInsert(jsonA2, putResultA2), + ]) + ); + + expect(syncResult1.changes.remote.length).toBe(2); + expect(syncResult1.changes.remote).toEqual( + expect.arrayContaining([ + getChangedFileUpdateBySHA( + jsonA1, + putResultA1.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + getChangedFileInsert(jsonB3, putResultB3), + ]) + ); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: mergedDoc, + strategy: 'ours-diff', + operation: 'insert-merge', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([mergedJson, jsonA2, jsonB3]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([mergedJson, jsonA2, jsonB3]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: + * dbA : jsonA1 + * dbB : jsonB1 + * after : jsonA1 + * + * 3-way merge: + * jsonA1: 5 - Conflict. Accept theirs (insert) + */ + it('resolves case 5 - Conflict. Accept theirs (insert)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'theirs-diff', + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B puts the same file + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + const mergedJson = { _id: '1', name: 'fromA' }; + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.json'); + + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1, + `resolve: 1${JSON_POSTFIX}(insert-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(insert-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1!.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + ]); + + expect(syncResult1.changes.remote.length).toBe(0); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: mergedDoc, + strategy: 'theirs-diff', + operation: 'insert-merge', + }, + ]); + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : -jsonA1 + * result: + * + * '+' means update + * + * 3-way merge: + * jsonA1: 8 - Conflict. Accept ours (delete) + */ + it('resolves case 8 - Conflict. Accept ours (delete)', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours-diff', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A updates and pushes + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B removes and syncs + const deleteResultB1 = await dbB.delete(jsonA1); + + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultB1.fileOid.substr( + 0, + 7 + )},ours-diff)`, + ]), + remote: getCommitInfo([ + deleteResultB1, + `resolve: 1${JSON_POSTFIX}(delete,${deleteResultB1.fileOid.substr( + 0, + 7 + )},ours-diff)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(0); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileDelete(jsonA1dash, putResultA1dash), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: deleteResultB1.fileOid, + type: 'json', + doc: jsonA1, + }, + strategy: 'ours-diff', + operation: 'delete', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : -jsonA1 jsonA2 + * dbB : jsonB1 + * result: jsonB1 jsonA2 + * + * 3-way merge: + * jsonB1: 11 - Conflict. Accept ours (update) + * jsonA2: 1 - Accept theirs (insert) + */ + it('resolves case 11 - Conflict. Accept ours (update), case 1 - Accept theirs (insert), ', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours-diff', + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A removes the old file and puts a new file + const deleteResultA1 = await dbA.delete(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B updates the old file and syncs + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + deleteResultA1, + putResultA2, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours-diff)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(update,${putResultB1.fileOid.substr(0, 7)},ours-diff)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA2, putResultA2), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileInsert(jsonB1, putResultB1), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: { + _id: '1', + name: '1.json', + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + strategy: 'ours-diff', + operation: 'update', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : mergedJson + * + * 3-way merge: + * mergedJson:17 - Conflict. Accept theirs (update-merge) + */ + it('resolves case 17 - Conflict. Accept theirs (update-merge)', async () => { + const schema: Schema = { + json: { plainTextProperties: { name: true } }, + }; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'theirs-diff', + connection, + }, + schema + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'Hello, world!' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + schema, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'theirs-diff', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'Hello' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'Hello, world! Hello, Nara!' }; + const putResultB1 = await dbB.put(jsonB1); + + const mergedJson = { _id: '1', name: 'Hello Hello, Nara!' }; + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.json'); + + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${JSON_POSTFIX}(update-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${JSON_POSTFIX}(update-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdateBySHA( + jsonA1dash, + putResultA1dash.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: mergedDoc, + strategy: 'theirs-diff', + operation: 'update-merge', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB)).toEqual([mergedJson]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([mergedJson]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : mergedJson + * + * 3-way merge: + * mergedJson:17 - Conflict. Accept theirs (update-merge) + */ + it('resolves case 17 - Conflict. Accept theirs (update-merge) in FrontMatterMarkdown with .yml', async () => { + const schema: Schema = { + json: { plainTextProperties: { name: true } }, + }; + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir, + schema, + serialize: 'front-matter', + }); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + includeCommits: true, + conflictResolutionStrategy: 'theirs-diff', + connection, + }; + + await dbA.open(); + const syncA = await dbA.sync(options); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'Hello, world!' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + schema, + serialize: 'front-matter', + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'theirs-diff', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'Hello' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'Hello, world! Hello, Nara!' }; + const putResultB1 = await dbB.put(jsonB1); + + const mergedJson = { _id: '1', name: 'Hello Hello, Nara!' }; + + // It will occur conflict on id 1.yml. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.yml'); + + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${YAML_POSTFIX}(update-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${YAML_POSTFIX}(update-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1.fileOid, + mergedJson, + mergedDoc!.fileOid, + dbA.serializeFormat + ), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdateBySHA( + jsonA1dash, + putResultA1dash.fileOid, + mergedJson, + mergedDoc!.fileOid, + dbA.serializeFormat + ), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: mergedDoc, + strategy: 'theirs-diff', + operation: 'update-merge', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB, new SerializeFormatFrontMatter())).toEqual([ + mergedJson, + ]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA, new SerializeFormatFrontMatter())).toEqual([ + mergedJson, + ]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : mergedJson + * + * 3-way merge: + * mergedJson:17 - Conflict. Accept theirs (update-merge) + */ + it('resolves case 17 - Conflict. Accept theirs (update-merge) in FrontMatterMarkdown with .md', async () => { + const schema: Schema = { + json: { plainTextProperties: { name: true, _body: true } }, + }; + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir, + schema, + serialize: 'front-matter', + }); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + includeCommits: true, + conflictResolutionStrategy: 'theirs-diff', + connection, + }; + + await dbA.open(); + const syncA = await dbA.sync(options); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'Hello, world!', _body: 'Hello, world!' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + schema, + serialize: 'front-matter', + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'theirs-diff', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'Hello', _body: 'Welcome!' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { + _id: '1', + name: 'Hello, world! Hello, Nara!', + _body: 'Hello, world! Hello, Nara!', + }; + const putResultB1 = await dbB.put(jsonB1); + + const mergedJson = { + _id: '1', + name: 'Hello Hello, Nara!', + _body: 'Welcome! Hello, Nara!', + }; + + // It will occur conflict on id 1.yml. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.md'); + + expect(syncResult1.action).toBe('resolve conflicts and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([ + putResultA1dash, + `resolve: 1${FRONT_MATTER_POSTFIX}(update-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + remote: getCommitInfo([ + putResultB1, + `resolve: 1${FRONT_MATTER_POSTFIX}(update-merge,${mergedDoc!.fileOid.substr( + 0, + 7 + )},theirs-diff)`, + ]), + }); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1.fileOid, + mergedJson, + mergedDoc!.fileOid, + dbA.serializeFormat + ), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdateBySHA( + jsonA1dash, + putResultA1dash.fileOid, + mergedJson, + mergedDoc!.fileOid, + dbA.serializeFormat + ), + ]); + + expect(syncResult1.conflicts.length).toEqual(1); + expect(syncResult1.conflicts).toEqual([ + { + fatDoc: mergedDoc, + strategy: 'theirs-diff', + operation: 'update-merge', + }, + ]); + // Conflict occurs on 1.json + + expect(getWorkingDirDocs(dbB, new SerializeFormatFrontMatter())).toEqual([ + mergedJson, + ]); + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA, new SerializeFormatFrontMatter())).toEqual([ + mergedJson, + ]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + describe('plaintext-OT Type', () => { + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : mergedJson + * + * 3-way merge: + * mergedJson:17 - Conflict. Accept theirs (update-merge) + */ + it('add text', async () => { + const schema: Schema = { + json: { plainTextProperties: { name: true } }, + }; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours-diff', + connection, + }, + schema + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'Nara and Kyoto' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + schema, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'ours-diff', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'Hello, Nara and Kyoto' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'Nara and Kyoto and Osaka' }; + const putResultB1 = await dbB.put(jsonB1); + + const mergedJson = { _id: '1', name: 'Hello, Nara and Kyoto and Osaka' }; + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.json'); + + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + ]); + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : mergedJson + * + * 3-way merge: + * mergedJson:17 - Conflict. Accept theirs (update-merge) + */ + it('move text', async () => { + const schema: Schema = { + json: { plainTextProperties: { name: true } }, + }; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours-diff', + connection, + }, + schema + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'Nara Osaka Kyoto Nagoya' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + schema, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'ours-diff', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'Osaka Kyoto Nara Nagoya' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'Kyoto Nara Osaka Nagoya' }; + const putResultB1 = await dbB.put(jsonB1); + + const mergedJson = { _id: '1', name: 'Kyoto Osaka Nara Nagoya' }; + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.json'); + + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + ]); + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : jsonB1 + * after : mergedJson + * + * 3-way merge: + * mergedJson:17 - Conflict. Accept theirs (update-merge) + */ + it('bad result', async () => { + const schema: Schema = { + json: { plainTextProperties: { name: true } }, + }; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours-diff', + connection, + }, + schema + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'Nara Kyoto' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + schema, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + ...syncA.options, + conflictResolutionStrategy: 'ours-diff', + }); + + // A puts and pushes + const jsonA1dash = { _id: '1', name: 'Nara Kamo' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B puts + const jsonB1 = { _id: '1', name: 'Kyoto Nara' }; + const putResultB1 = await dbB.put(jsonB1); + + // ! Bad result. Best result is 'Kyoto Nara Kamo' + const mergedJson = { _id: '1', name: 'Kyoto ama' }; + + // It will occur conflict on id 1.json. + const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; + + const mergedDoc = await dbB.getFatDoc('1.json'); + + expect(syncResult1.changes.local).toEqual([ + getChangedFileUpdateBySHA( + jsonB1, + putResultB1.fileOid, + mergedJson, + mergedDoc!.fileOid + ), + ]); + await destroyDBs([dbA, dbB]); + }); + }); + }); +}; diff --git a/test/remote_base/combine.ts b/test/remote_base/combine.ts new file mode 100644 index 00000000..b6b25655 --- /dev/null +++ b/test/remote_base/combine.ts @@ -0,0 +1,744 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test combine databases + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ + +import fs from 'fs-extra'; +import git from 'isomorphic-git'; +import expect from 'expect'; +import parse from 'parse-git-config'; +import { Err } from '../../src/error'; +import { ConnectionSettings, DuplicatedFile, RemoteOptions } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { + compareWorkingDirAndBlobs, + createDatabase, + destroyDBs, + destroyRemoteRepository, + getWorkingDirDocs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { sleep } from '../../src/utils'; +import { FRONT_MATTER_POSTFIX, JSON_POSTFIX, YAML_POSTFIX } from '../../src/const'; +import { SerializeFormatFrontMatter } from '../../src/serialize_format'; + +export const syncCombineBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe('', () => { + /** + * Combine database + */ + describe('with same serializeFormat', () => { + it('throws NoMergeBaseFoundError when combineDbStrategy is throw-error in [both] direction', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'throw-error', + syncDirection: 'both', + connection, + } + ); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + // trySync throws NoMergeBaseFoundError + await expect(dbB.sync(syncA.options)).rejects.toThrowError( + Err.NoMergeBaseFoundError + ); + + // await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + // await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('commits with valid commit message for combine-head-with-theirs', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + // Need local commit to combine dbs with commit message. + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + // Combine with remote db + await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( + Err.NoMergeBaseFoundError + ); + + const headCommitOid = await git.resolveRef({ + fs, + dir: dbB.workingDir, + ref: 'HEAD', + }); + const headCommit = await git.readCommit({ + fs, + dir: dbB.workingDir, + oid: headCommitOid, + }); + expect(headCommit.commit.message).toEqual(`combine database head with theirs\n`); + + await destroyDBs([dbA, dbB]); + }); + + it('succeeds when combine-head-with-theirs with empty local and empty remote', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + // Combine with remote db + await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( + Err.NoMergeBaseFoundError + ); + + // Put new doc to combined db. + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + + expect(getWorkingDirDocs(dbA)).toEqual([]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('succeeds combine-head-with-theirs with empty local and not empty remote', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.trySync(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + // Combine with remote db + await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( + Err.NoMergeBaseFoundError + ); + + // Put new doc to combined db. + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('succeeds when combine-head-with-theirs with not empty local and empty remote', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + // Combine with remote db + await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( + Err.NoMergeBaseFoundError + ); + + // Put new doc to combined db. + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + + expect(getWorkingDirDocs(dbA)).toEqual([]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('succeeds when combine-head-with-theirs with deep local and deep remote', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + const jsonA1 = { _id: 'deep/one', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.trySync(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + const jsonB2 = { + _id: 'item/box01F76SNGYBWA5PBAYR0GNNT3Y4/item01F76SP8HNANY5QAXZ53DEHXBJ', + name: 'fromB', + }; + await dbB.put(jsonB2); + + // Combine with remote db + await dbB.sync(syncA.options); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('returns SyncResult with duplicates when combine-head-with-theirs with not empty local and not empty remote', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + const dbIdA = dbA.dbId; + + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.trySync(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + const dbIdB = dbB.dbId; + expect(dbIdB).not.toBe(dbIdA); + + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + + // Combine with remote db + const [sync, syncResult] = await dbB.sync(syncA.options, true); + + expect(dbB.dbId).toBe(dbIdA); + + // Put new doc to combined db. + const jsonB3 = { _id: '3', name: 'fromB' }; + await dbB.put(jsonB3); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + // jsonB1 is duplicated with postfix due to combine-head-with-theirs strategy + jsonB1._id = jsonB1._id + '-from-' + dbIdB; + const duplicatedB1 = await dbB.getFatDoc(jsonB1._id + JSON_POSTFIX); + + expect(syncResult).toEqual({ + action: 'combine database', + duplicates: [ + { + original: { + _id: jsonA1._id, + name: jsonA1._id + JSON_POSTFIX, + fileOid: putResultA1.fileOid, + type: 'json', + }, + duplicate: { + _id: jsonB1._id, + name: jsonB1._id + JSON_POSTFIX, + fileOid: duplicatedB1?.fileOid, + type: 'json', + }, + }, + ], + }); + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA1, jsonB2, jsonB3]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('returns SyncResult with duplicates when combine-head-with-theirs with deep local and deep remote', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + const dbIdA = dbA.dbId; + + const jsonA1 = { _id: 'deep/one', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.trySync(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + const dbIdB = dbB.dbId; + expect(dbIdB).not.toBe(dbIdA); + + const jsonB1 = { _id: 'deep/one', name: 'fromB' }; + await dbB.put(jsonB1); + + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + + // Combine with remote db + const [sync, syncResult] = await dbB.sync(syncA.options, true); + + expect(dbB.dbId).toBe(dbIdA); + + // Put new doc to combined db. + const jsonB3 = { _id: '3', name: 'fromB' }; + await dbB.put(jsonB3); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + // jsonB1 is duplicated with postfix due to combine-head-with-theirs strategy + jsonB1._id = jsonB1._id + '-from-' + dbIdB; + const duplicatedB1 = await dbB.getFatDoc(jsonB1._id + JSON_POSTFIX); + + expect(syncResult).toEqual({ + action: 'combine database', + duplicates: [ + { + original: { + _id: jsonA1._id, + name: jsonA1._id + JSON_POSTFIX, + fileOid: putResultA1.fileOid, + type: 'json', + }, + duplicate: { + _id: jsonB1._id, + name: jsonB1._id + JSON_POSTFIX, + fileOid: duplicatedB1?.fileOid, + type: 'json', + }, + }, + ], + }); + expect(getWorkingDirDocs(dbB)).toEqual([jsonB2, jsonB3, jsonB1, jsonA1]); + + const rawJSON = fs.readJSONSync(dbB.workingDir + '/deep/one.json'); + rawJSON._id = 'one'; // not 'deep/one' + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('invokes combine event with duplicates when combine-head-with-theirs with not empty local and not empty remote', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + let duplicatedFiles: DuplicatedFile[] = []; + syncA.on('combine', (duplicates: DuplicatedFile[]) => { + duplicatedFiles = [...duplicates]; + }); + + const dbIdA = dbA.dbId; + + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + + // Delete remote repository + await destroyRemoteRepository(syncA.remoteURL); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + + const dbIdB = dbB.dbId; + + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + + // Create and push to new remote repository + const syncB = await dbB.sync(syncA.options); + // Combine database on A + await syncA.trySync().catch(async () => { + await dbA.destroy(); + }); + + jsonA1._id = jsonA1._id + '-from-' + dbIdA; + const duplicatedA1 = await dbA.getFatDoc(jsonA1._id + JSON_POSTFIX); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonB1, jsonB2]); + // jsonA1 is duplicated with postfix due to combine-head-with-theirs strategy + + while (duplicatedFiles.length === 0) { + // eslint-disable-next-line no-await-in-loop + await sleep(3000); + } + expect(duplicatedFiles).toEqual([ + { + original: { + _id: jsonB1._id, + name: jsonB1._id + JSON_POSTFIX, + fileOid: putResultB1.fileOid, + type: 'json', + }, + duplicate: { + _id: jsonA1._id, + name: jsonA1._id + JSON_POSTFIX, + fileOid: duplicatedA1?.fileOid, + type: 'json', + }, + }, + ]); + + // Push combined db + await syncA.trySync(); + // Pull combined db + await syncB.trySync(); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB1, jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + it('copies author from local repository', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + } + ); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + await dbB.open(); + const author = { + name: 'foo', + email: 'bar@localhost', + }; + dbB.author = author; + await dbB.saveAuthor(); + + // Combine with remote db + await expect(dbB.sync(syncA.options)).resolves.not.toThrowError( + Err.NoMergeBaseFoundError + ); + + const config = parse.sync({ cwd: dbB.workingDir, path: '.git/config' }); + expect(config.user).toEqual(author); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe('with same serializeFormat (front-matter)', () => { + it('returns SyncResult with duplicates when combine-head-with-theirs with deep local and deep remote', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir, + serialize: 'front-matter', + }); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + }; + + await dbA.open(); + const syncA = await dbA.sync(options); + + const dbIdA = dbA.dbId; + + const jsonA1 = { _id: 'deep/one', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.trySync(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + serialize: 'front-matter', + }); + await dbB.open(); + + const dbIdB = dbB.dbId; + expect(dbIdB).not.toBe(dbIdA); + + const jsonB1 = { _id: 'deep/one', name: 'fromB' }; + await dbB.put(jsonB1); + + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + + // Combine with remote db + const [sync, syncResult] = await dbB.sync(syncA.options, true); + + expect(dbB.dbId).toBe(dbIdA); + + // Put new doc to combined db. + const jsonB3 = { _id: '3', name: 'fromB' }; + await dbB.put(jsonB3); + + expect(getWorkingDirDocs(dbA, new SerializeFormatFrontMatter())).toEqual([jsonA1]); + // jsonB1 is duplicated with postfix due to combine-head-with-theirs strategy + jsonB1._id = jsonB1._id + '-from-' + dbIdB; + const duplicatedB1 = await dbB.getFatDoc(jsonB1._id + YAML_POSTFIX); + + expect(syncResult).toEqual({ + action: 'combine database', + duplicates: [ + { + original: { + _id: jsonA1._id, + name: jsonA1._id + YAML_POSTFIX, + fileOid: putResultA1.fileOid, + type: 'json', + }, + duplicate: { + _id: jsonB1._id, + name: jsonB1._id + YAML_POSTFIX, + fileOid: duplicatedB1?.fileOid, + type: 'json', + }, + }, + ], + }); + expect(getWorkingDirDocs(dbB, new SerializeFormatFrontMatter())).toEqual([ + jsonB2, + jsonB3, + jsonB1, + jsonA1, + ]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + }); + + it('includes files which have the same name with another extension (.md, .yml)', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir, + serialize: 'front-matter', + }); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + combineDbStrategy: 'combine-head-with-theirs', + syncDirection: 'both', + connection, + }; + + await dbA.open(); + const syncA = await dbA.sync(options); + + const dbIdA = dbA.dbId; + + const jsonA1 = { _id: 'deep/one', name: 'fromA', _body: 'foo' }; // deep/one.md (FrontMatter + Markdown) + await dbA.put(jsonA1); + await syncA.trySync(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + serialize: 'front-matter', + }); + await dbB.open(); + + const dbIdB = dbB.dbId; + expect(dbIdB).not.toBe(dbIdA); + + const jsonB1 = { _id: 'deep/one', name: 'fromB' }; // deep/one.yml (YAML) + await dbB.put(jsonB1); + + // Combine with remote db + const [sync, syncResult] = await dbB.sync(syncA.options, true); + + expect(dbB.dbId).toBe(dbIdA); + + expect(getWorkingDirDocs(dbA, new SerializeFormatFrontMatter())).toEqual([jsonA1]); + + // Not duplicate because extension is different. + const fatDocA = await dbB.getFatDoc(jsonA1._id + FRONT_MATTER_POSTFIX); + expect(fatDocA?.doc).toEqual(jsonA1); + + const fatDocB = await dbB.getFatDoc(jsonB1._id + YAML_POSTFIX); + expect(fatDocB?.doc).toEqual(jsonB1); + + expect(syncResult).toEqual({ + action: 'combine database', + duplicates: [], + }); + + expect(getWorkingDirDocs(dbB, new SerializeFormatFrontMatter())).toEqual([ + jsonA1, + jsonB1, + ]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + }); +}; diff --git a/test/remote_base/network_git_documentdb.ts b/test/remote_base/network_git_documentdb.ts new file mode 100644 index 00000000..e801e096 --- /dev/null +++ b/test/remote_base/network_git_documentdb.ts @@ -0,0 +1,123 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for GitDocumentDB class + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ + +import expect from 'expect'; +import { ConnectionSettings, RemoteOptions } from '../../src/types'; +import { destroyDBs, removeRemoteRepositories } from '../remote_utils'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { Err } from '../../src/error'; + +export const networkGitDocumentDBBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + /** + * Initialize synchronization by open() with remoteURL + * Initialize means creating local and remote repositories by using a remoteUrl + */ + describe(' Sync is initialized from GitDocumentDB():', () => { + it('sync() returns an instance of Sync.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + expect(syncA.remoteURL).toBe(remoteURL); + await destroyDBs([dbA]); + }); + + it('unregisterRemote() removes an instance of Sync.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + await dbA.sync(options); + dbA.removeSync(remoteURL); + expect(dbA.getSync(remoteURL)).toBeUndefined(); + await destroyDBs([dbA]); + }); + + it('throws RemoteAlreadyRegisteredError when sync() the same url twice.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + + await dbA.open(); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const syncA = await dbA.sync(options); + await expect(dbA.sync(options)).rejects.toThrowError( + Err.RemoteAlreadyRegisteredError + ); + await dbA.destroy(); + }); + + it('getRemoteURLs() returns sync', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + logLevel: 'trace', + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + await dbA.sync(options); + const remoteURL2 = remoteURLBase + serialId(); + const options2: RemoteOptions = { + remoteUrl: remoteURL2, + connection, + }; + await dbA.sync(options2); + expect(dbA.getRemoteURLs()).toEqual([remoteURL, remoteURL2]); + await destroyDBs([dbA]); + }); + }); +}; diff --git a/test/remote_base/network_history.ts b/test/remote_base/network_history.ts new file mode 100644 index 00000000..324a3f45 --- /dev/null +++ b/test/remote_base/network_history.ts @@ -0,0 +1,188 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for history + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ + +import expect from 'expect'; +import { ConnectionSettings } from '../../src/types'; +import { + createClonedDatabases, + destroyDBs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { sleep, toSortedJSONString, utf8encode } from '../../src/utils'; +import { JSON_POSTFIX } from '../../src/const'; +import { getHistoryImpl, readOldBlob } from '../../src/crud/history'; + +export const networkHistoryBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe(' getHistoryImpl', () => { + it('gets all revisions sorted by date from merged commit', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + + const _id = 'prof'; + const shortName = _id + JSON_POSTFIX; + const jsonA1 = { _id, name: 'A-1' }; + const jsonA2 = { _id, name: 'A-2' }; + const jsonA3 = { _id, name: 'A-3' }; + const jsonB1 = { _id, name: 'B-1' }; + const jsonB2 = { _id, name: 'B-2' }; + const putResultA1 = await dbA.put(jsonA1); + await sleep(1500); + const putResultB1 = await dbB.put(jsonB1); + await sleep(1500); + const putResultA2 = await dbA.put(jsonA2); + await sleep(1500); + const putResultB2 = await dbB.put(jsonB2); + await sleep(1500); + const putResultA3 = await dbA.put(jsonA3); + await sleep(1500); + + await syncA.trySync(); + await syncB.trySync(); // Resolve conflict. jsonB2 wins. + + // Get + const history = await getHistoryImpl( + dbB, + shortName, + '', + dbB.serializeFormat, + undefined, + undefined, + true + ); + + expect(history[0]).toEqual({ + _id, + name: shortName, + fileOid: expect.stringMatching(/^[\da-z]{40}$/), + type: 'json', + doc: jsonB2, + }); + expect(history[1]).toEqual({ + _id, + name: shortName, + fileOid: expect.stringMatching(/^[\da-z]{40}$/), + type: 'json', + doc: jsonA3, + }); + expect(history[2]).toEqual({ + _id, + name: shortName, + fileOid: expect.stringMatching(/^[\da-z]{40}$/), + type: 'json', + doc: jsonB2, + }); + expect(history[3]).toEqual({ + _id, + name: shortName, + fileOid: expect.stringMatching(/^[\da-z]{40}$/), + type: 'json', + doc: jsonA2, + }); + expect(history[4]).toEqual({ + _id, + name: shortName, + fileOid: expect.stringMatching(/^[\da-z]{40}$/), + type: 'json', + doc: jsonB1, + }); + expect(history[5]).toEqual({ + _id, + name: shortName, + fileOid: expect.stringMatching(/^[\da-z]{40}$/), + type: 'json', + doc: jsonA1, + }); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe(' readOldBlob()', () => { + it('skips a merge commit', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + conflictResolutionStrategy: 'ours', + connection, + } + ); + dbA.author = { + name: 'authorA', + email: 'authorEmailA', + }; + dbB.author = { + name: 'authorB', + email: 'authorEmailB', + }; + + const jsonA1 = { _id: 'A1', name: 'A1' }; + const jsonA1internal = { _id: 'A1', name: 'A1' }; + const jsonB1 = { _id: 'B1', name: 'B1' }; + const putResultA1 = await dbA.put(jsonA1); + await sleep(1500); + await dbB.put(jsonB1); + await sleep(1500); + + await syncA.trySync(); + await syncB.trySync(); // dbB commits 'merge' + + await expect( + readOldBlob(dbB.workingDir, 'A1.json', 0, { filter: [{ author: dbB.author }] }) + ).resolves.toBeUndefined(); // merge commit is skipped, so jsonA1 does not exist. + + await expect( + readOldBlob(dbB.workingDir, 'A1.json', 0, { filter: [{ author: dbA.author }] }) + ).resolves.toEqual({ + oid: putResultA1.fileOid, + blob: utf8encode(toSortedJSONString(jsonA1internal)), + }); + + await destroyDBs([dbA, dbB]); + }); + }); +}; diff --git a/test/remote_base/network_task_queue.ts b/test/remote_base/network_task_queue.ts new file mode 100644 index 00000000..1bd5beb8 --- /dev/null +++ b/test/remote_base/network_task_queue.ts @@ -0,0 +1,123 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for TaskQueue + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ + +import expect from 'expect'; +import { ConnectionSettings } from '../../src/types'; +import { + createDatabase, + destroyDBs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; + +export const networkTaskQueueBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe(' remote', () => { + it('increments statistics: push', async () => { + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + serialId, + { + connection, + }, + undefined + ); + + // The first push in open() + expect(dbA.taskQueue.currentStatistics().push).toBe(1); + + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + expect(dbA.taskQueue.currentStatistics().push).toBe(2); + + await destroyDBs([dbA]); + }); + + it('increments statistics: sync', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + expect(dbA.taskQueue.currentStatistics().sync).toBe(0); + + await syncA.trySync(); + expect(dbA.taskQueue.currentStatistics().sync).toBe(1); + + await destroyDBs([dbA]); + }); + + it('clear() statistics', async () => { + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + serialId, + { + connection, + } + ); + + await syncA.trySync(); + expect(dbA.taskQueue.currentStatistics()).toEqual({ + put: 0, + insert: 0, + update: 0, + delete: 0, + push: 1, + sync: 1, + cancel: 0, + }); + dbA.taskQueue.stop(); + expect(dbA.taskQueue.currentStatistics()).toEqual({ + put: 0, + insert: 0, + update: 0, + delete: 0, + push: 0, + sync: 0, + cancel: 0, + }); + await destroyDBs([dbA]); + }); + }); +}; diff --git a/test/remote_base/on_sync_event.ts b/test/remote_base/on_sync_event.ts new file mode 100644 index 00000000..f77f9a90 --- /dev/null +++ b/test/remote_base/on_sync_event.ts @@ -0,0 +1,446 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test Operational Transformation in 3-way merge + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import expect from 'expect'; +import { Err } from '../../src/error'; +import { + ConnectionSettings, + SyncResult, + SyncResultFastForwardMerge, + TaskMetadata, +} from '../../src/types'; +import { + createClonedDatabases, + destroyDBs, + getChangedFileInsert, + getCommitInfo, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { sleep } from '../../src/utils'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +export const onSyncEventBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe(' GitDocumentDB', () => { + describe('onSyncEvent', () => { + it('with remoteURL', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B syncs + let result: SyncResultFastForwardMerge | undefined; + let changeTaskId = ''; + + dbB.onSyncEvent( + syncB.remoteURL, + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + result = syncResult as SyncResultFastForwardMerge; + changeTaskId = taskMetadata.taskId; + } + ); + let complete = false; + let endTaskId = ''; + dbB.onSyncEvent(syncB.remoteURL, 'complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(result!.action).toBe('fast-forward merge'); + + expect(result!.commits).toMatchObject({ + local: getCommitInfo([putResult1]), + }); + + expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); + + expect(changeTaskId).toBe(endTaskId); + + await destroyDBs([dbA, dbB]); + }); + + it('with remoteURL throws UndefinedSyncError', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + + expect(() => { + dbA.onSyncEvent('https://test.example.com', 'change', () => {}); + }).toThrowError(Err.UndefinedSyncError); + + await destroyDBs([dbA]); + }); + + it('with sync', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B syncs + let result: SyncResultFastForwardMerge | undefined; + let changeTaskId = ''; + + dbB.onSyncEvent( + syncB, + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + result = syncResult as SyncResultFastForwardMerge; + changeTaskId = taskMetadata.taskId; + } + ); + let complete = false; + let endTaskId = ''; + dbB.onSyncEvent(syncB, 'complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(result!.action).toBe('fast-forward merge'); + + expect(result!.commits).toMatchObject({ + local: getCommitInfo([putResult1]), + }); + + expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); + + expect(changeTaskId).toBe(endTaskId); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe('offSyncEvent', () => { + it('with remoteURL', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; + dbB.onSyncEvent(syncB.remoteURL, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(1); + dbB.offSyncEvent(syncB.remoteURL, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(0); + + await destroyDBs([dbA, dbB]); + }); + + it('with remoteURL throws UndefinedSyncError', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + + expect(() => { + dbA.offSyncEvent('https://test.example.com', 'change', () => {}); + }).toThrowError(Err.UndefinedSyncError); + + await destroyDBs([dbA]); + }); + + it('with sync', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; + dbB.onSyncEvent(syncB, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(1); + dbB.offSyncEvent(syncB, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(0); + + await destroyDBs([dbA, dbB]); + }); + }); + }); + + describe(' Collection', () => { + describe('onSyncEvent', () => { + it('with remoteURL', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + const colA = dbA.collection('col'); + const colB = dbB.collection('col'); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await colA.put(jsonA1); + await syncA.tryPush(); + + // B syncs + let result: SyncResultFastForwardMerge | undefined; + let changeTaskId = ''; + + colB.onSyncEvent( + syncB.remoteURL, + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + result = syncResult as SyncResultFastForwardMerge; + changeTaskId = taskMetadata.taskId; + } + ); + let complete = false; + let endTaskId = ''; + colB.onSyncEvent(syncB.remoteURL, 'complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(result!.action).toBe('fast-forward merge'); + + expect(result!.commits).toMatchObject({ + local: getCommitInfo([putResult1]), + }); + + expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); + + expect(changeTaskId).toBe(endTaskId); + + await destroyDBs([dbA, dbB]); + }); + + it('with remoteURL throws UndefinedSyncError', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const colA = dbA.collection('col'); + expect(() => { + colA.onSyncEvent('https://test.example.com', 'change', () => {}); + }).toThrowError(Err.UndefinedSyncError); + + await destroyDBs([dbA]); + }); + + it('with sync', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const colA = dbA.collection('col'); + const colB = dbB.collection('col'); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await colA.put(jsonA1); + await syncA.tryPush(); + + // B syncs + let result: SyncResultFastForwardMerge | undefined; + let changeTaskId = ''; + + colB.onSyncEvent( + syncB, + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + result = syncResult as SyncResultFastForwardMerge; + changeTaskId = taskMetadata.taskId; + } + ); + let complete = false; + let endTaskId = ''; + colB.onSyncEvent(syncB, 'complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(result!.action).toBe('fast-forward merge'); + + expect(result!.commits).toMatchObject({ + local: getCommitInfo([putResult1]), + }); + + expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); + + expect(changeTaskId).toBe(endTaskId); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe('offSyncEvent', () => { + it('with remoteURL', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const colB = dbB.collection('col'); + const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; + colB.onSyncEvent(syncB.remoteURL, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(1); + colB.offSyncEvent(syncB.remoteURL, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(0); + + await destroyDBs([dbA, dbB]); + }); + + it('with remoteURL throws UndefinedSyncError', async () => { + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + + const colA = dbA.collection('col'); + + expect(() => { + colA.offSyncEvent('https://test.example.com', 'change', () => {}); + }).toThrowError(Err.UndefinedSyncError); + + await destroyDBs([dbA]); + }); + + it('with sync', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const colB = dbB.collection('col'); + + const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; + colB.onSyncEvent(syncB, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(1); + colB.offSyncEvent(syncB, 'change', callback); + expect(syncB.eventHandlers.change.length).toBe(0); + + await destroyDBs([dbA, dbB]); + }); + }); + }); +}; diff --git a/test/remote_base/sync.ts b/test/remote_base/sync.ts new file mode 100644 index 00000000..e256e2fd --- /dev/null +++ b/test/remote_base/sync.ts @@ -0,0 +1,1179 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test constructor + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ + +import crypto from 'crypto'; +import fs from 'fs'; +import { Octokit } from '@octokit/rest'; +import git from 'isomorphic-git'; +import expect from 'expect'; +import sinon from 'sinon'; +import * as RemoteEngineErr from 'git-documentdb-remote-errors'; +import { sleep } from '../../src/utils'; +import { MINIMUM_SYNC_INTERVAL } from '../../src/const'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { ConnectionSettings, RemoteOptions } from '../../src/types'; +import { Err } from '../../src/error'; +import { encodeToGitRemoteName, Sync, syncImpl } from '../../src/remote/sync'; +import { + createClonedDatabases, + createRemoteRepository, + destroyDBs, + removeRemoteRepositories, +} from '../remote_utils'; +import { RemoteEngine, RemoteErr } from '../../src/remote/remote_engine'; + +export const syncBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string, + token: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + // Use sandbox to restore stub and spy in parallel mocha tests + let sandbox: sinon.SinonSandbox; + beforeEach(function () { + // To avoid secondary rate limit of GitHub + // await new Promise(resolve => setTimeout(resolve, 3000)); + + sandbox = sinon.createSandbox(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + before(async () => { + // Remove remote + await removeRemoteRepositories(reposPrefix); + }); + + describe(' encodeToGitRemoteName', () => { + it('always generates the same name', async () => { + const remoteURL = 'ssh://user@github.com:443/foo-bar/baz.git'; + const encoded = encodeToGitRemoteName(remoteURL); + await sleep(1500); + const encoded2 = encodeToGitRemoteName(remoteURL); + expect(encoded).toBe(encoded2); + }); + + it('encodes ssh://user@github.com:443/foo-bar/baz.git', () => { + const remoteURL = 'ssh://user@github.com:443/foo-bar/baz.git'; + const encoded = encodeToGitRemoteName(remoteURL); + const shortHash = crypto + .createHash('sha1') + .update(remoteURL) + .digest('hex') + .substr(0, 7); + expect(encoded).toBe('github_com_' + shortHash); + }); + + it('encodes ssh://user@127.0.0.1:443/foo-bar/baz.git', () => { + const remoteURL = 'ssh://user@127.0.0.1:443/foo-bar/baz.git'; + const encoded = encodeToGitRemoteName(remoteURL); + const shortHash = crypto + .createHash('sha1') + .update(remoteURL) + .digest('hex') + .substr(0, 7); + expect(encoded).toBe('127_0_0_1_' + shortHash); + }); + + it('encodes https://github.com:80/foo-bar/baz.git', () => { + const remoteURL = 'https://github.com:80/foo-bar/baz.git'; + const encoded = encodeToGitRemoteName(remoteURL); + const shortHash = crypto + .createHash('sha1') + .update(remoteURL) + .digest('hex') + .substr(0, 7); + expect(encoded).toBe('github_com_' + shortHash); + }); + + it('encodes ssh://user@github.com/foo-bar/baz.git', () => { + const remoteURL = 'ssh://user@github.com/foo-bar/baz.git'; + const encoded = encodeToGitRemoteName(remoteURL); + const shortHash = crypto + .createHash('sha1') + .update(remoteURL) + .digest('hex') + .substr(0, 7); + expect(encoded).toBe('github_com_' + shortHash); + }); + + it('encodes https://github.com/foo-bar/baz.git', () => { + const remoteURL = 'https://github.com/foo-bar/baz.git'; + const encoded = encodeToGitRemoteName(remoteURL); + const shortHash = crypto + .createHash('sha1') + .update(remoteURL) + .digest('hex') + .substr(0, 7); + expect(encoded).toBe('github_com_' + shortHash); + }); + + it('encodes git@github.com:foo-bar/baz.git', () => { + const remoteURL = 'git@github.com:foo-bar/baz.git'; + const encoded = encodeToGitRemoteName(remoteURL); + const shortHash = crypto + .createHash('sha1') + .update(remoteURL) + .digest('hex') + .substr(0, 7); + expect(encoded).toBe('github_com_' + shortHash); + }); + + it('throws InvalidURLFormatError', () => { + const remoteURL = 'foo.bar'; + expect(() => { + encodeToGitRemoteName(remoteURL); + }).toThrowError(RemoteErr.InvalidURLFormatError); + }); + }); + + /** + * Tests for constructor + */ + describe(' constructor', () => { + it('set live to false by default', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = new Sync(gitDDB, options); + expect(sync.options.live).toBe(false); + + await gitDDB.destroy(); + }); + + it('set syncDirection to both by default', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = new Sync(gitDDB, options); + expect(sync.options.syncDirection).toBe('both'); + + await gitDDB.destroy(); + }); + + it('set combineDbStrategy to combine-head-with-theirs by default', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = new Sync(gitDDB, options); + expect(sync.options.combineDbStrategy).toBe('combine-head-with-theirs'); + + await gitDDB.destroy(); + }); + + it('set includeCommits to false by default', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = new Sync(gitDDB, options); + expect(sync.options.includeCommits).toBe(false); + + await gitDDB.destroy(); + }); + + it('set conflictResolutionStrategy to ours-diff by default', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = new Sync(gitDDB, options); + expect(sync.options.conflictResolutionStrategy).toBe('ours-diff'); + + await gitDDB.destroy(); + }); + + it('accepts remoteURL which ends with .git', async () => { + const remoteURL = remoteURLBase + commonId() + '.git'; + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + expect(() => new Sync(gitDDB, options)).not.toThrowError(); + + await gitDDB.destroy(); + }); + + it('throws UndefinedRemoteURLError when remoteURL is undefined.', async () => { + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + connection: { + type: 'github', + personalAccessToken: '', + }, + }; + expect(() => new Sync(gitDDB, options)).toThrowError(Err.UndefinedRemoteURLError); + await gitDDB.destroy(); + }); + + it('throws IntervalTooSmallError when interval is less than minimumSyncInterval.', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const invalid_options: RemoteOptions = { + remoteUrl: remoteURL, + interval: MINIMUM_SYNC_INTERVAL - 1, + connection: { + type: 'github', + personalAccessToken: '', + }, + }; + expect(() => new Sync(gitDDB, invalid_options)).toThrowError( + Err.IntervalTooSmallError + ); + await gitDDB.destroy(); + + await gitDDB.open(); + const valid_options: RemoteOptions = { + remoteUrl: remoteURL, + interval: MINIMUM_SYNC_INTERVAL, + connection, + }; + expect(() => new Sync(gitDDB, valid_options)).not.toThrowError(); + + await gitDDB.destroy(); + }); + + it('throws SyncIntervalLessThanOrEqualToRetryIntervalError', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const retryInterval = 5000; + const options: RemoteOptions = { + remoteUrl: remoteURL, + interval: retryInterval - 1, + retryInterval, + connection, + }; + // less than + expect(() => new Sync(gitDDB, options)).toThrowError( + Err.SyncIntervalLessThanOrEqualToRetryIntervalError + ); + await gitDDB.destroy(); + + // equal to + await gitDDB.open(); + options.interval = retryInterval; + expect(() => new Sync(gitDDB, options)).toThrowError( + Err.SyncIntervalLessThanOrEqualToRetryIntervalError + ); + await gitDDB.destroy(); + + // more than + await gitDDB.open(); + // eslint-disable-next-line require-atomic-updates + options.interval = retryInterval + 1; + expect(() => new Sync(gitDDB, options)).not.toThrowError(); + + await gitDDB.destroy(); + }); + }); + + describe(' init()', () => { + it('throws RemoteErr.InvalidURLFormatError.', async () => { + const dbName = serialId(); + const remoteURL = remoteURLBase + serialId; + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const stubFetch = sandbox.stub(RemoteEngine[connection.engine!], 'fetch'); + stubFetch.onFirstCall().rejects(new RemoteEngineErr.InvalidURLFormatError('')); + + const sync = new Sync(gitDDB, options); + await expect(sync.init()).rejects.toThrowError(RemoteErr.InvalidURLFormatError); + await gitDDB.destroy(); + }); + + it('throws RemoteErr.InvalidRepositoryURLError.', async () => { + const dbName = serialId(); + const remoteURL = remoteURLBase + commonId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const stubFetch = sandbox.stub(RemoteEngine[connection.engine!], 'fetch'); + stubFetch.onFirstCall().rejects(new RemoteEngineErr.InvalidRepositoryURLError('')); + + const sync = new Sync(gitDDB, options); + await expect(sync.init()).rejects.toThrowError(RemoteErr.InvalidRepositoryURLError); + await gitDDB.destroy(); + }); + + it('throws RemoteErr.InvalidSSHKeyPathError.', async () => { + const dbName = serialId(); + const remoteURL = remoteURLBase + commonId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const stubFetch = sandbox.stub(RemoteEngine[connection.engine!], 'fetch'); + stubFetch.onFirstCall().rejects(new RemoteEngineErr.InvalidSSHKeyPathError()); + + const sync = new Sync(gitDDB, options); + await expect(sync.init()).rejects.toThrowError(RemoteErr.InvalidSSHKeyPathError); + await gitDDB.destroy(); + }); + + it('throws RemoteErr.InvalidAuthenticationTypeError.', async () => { + const dbName = serialId(); + const remoteURL = remoteURLBase + commonId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const stubFetch = sandbox.stub(RemoteEngine[connection.engine!], 'fetch'); + stubFetch + .onFirstCall() + .rejects(new RemoteEngineErr.InvalidAuthenticationTypeError('')); + + const sync = new Sync(gitDDB, options); + await expect(sync.init()).rejects.toThrowError( + RemoteErr.InvalidAuthenticationTypeError + ); + await gitDDB.destroy(); + }); + + it('throws RemoteErr.HTTPError401AuthorizationRequired.', async () => { + const dbName = serialId(); + const remoteURL = remoteURLBase + commonId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const stubFetch = sandbox.stub(RemoteEngine[connection.engine!], 'fetch'); + stubFetch + .onFirstCall() + .rejects(new RemoteEngineErr.HTTPError401AuthorizationRequired('')); + + const sync = new Sync(gitDDB, options); + await expect(sync.init()).rejects.toThrowError( + RemoteErr.HTTPError401AuthorizationRequired + ); + await gitDDB.destroy(); + }); + + it('throws NetworkError', async () => { + const dbName = serialId(); + const remoteURL = remoteURLBase + commonId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const stubFetch = sandbox.stub(RemoteEngine[connection.engine!], 'fetch'); + stubFetch.rejects(new RemoteEngineErr.NetworkError('')); + + const sync = new Sync(gitDDB, options); + + await expect(sync.init()).rejects.toThrowError(RemoteErr.NetworkError); + + await gitDDB.destroy(); + }); + + it('throws CannotCreateRemoteRepositoryError', async () => { + const remoteURL = remoteURLBase + commonId(); + + const dbNameA = serialId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await gitDDB.open(); + + const sync = new Sync(gitDDB, options); + + const stubReposCreate = sandbox.stub(sync.remoteRepository, 'create'); + stubReposCreate + .onFirstCall() + .rejects(new Err.CannotConnectRemoteRepositoryError(0, '', '')); + + await expect(sync.init()).rejects.toThrowError(Err.CannotCreateRemoteRepositoryError); + + await gitDDB.destroy(); + }); + + it('creates a remote repository on GitHub by using personal access token', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await gitDDB.open(); + await gitDDB.sync(options); + + // Check remote + const octokit = new Octokit({ + auth: token, + }); + const urlArray = remoteURL.split('/'); + const owner = urlArray[urlArray.length - 2]; + const repo = urlArray[urlArray.length - 1]; + await expect(octokit.repos.listBranches({ owner, repo })).resolves.not.toThrowError(); + + await gitDDB.destroy(); + }); + + it('sets Git remote in .git/config', async () => { + const remoteURL = remoteURLBase + commonId(); + + const dbNameA = serialId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await gitDDB.open(); + await gitDDB.sync(options); + + const remoteName = encodeToGitRemoteName(remoteURL); + + const url = await git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.${remoteName}.url`, + }); + expect(url).toBe(remoteURL); + + const fetch = await git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.${encodeToGitRemoteName(remoteURL)}.fetch`, + }); + expect(fetch).toBe(`+refs/heads/*:refs/remotes/${remoteName}/*`); + + const originUrl = await git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.origin.url`, + }); + expect(originUrl).toBe(remoteURL); + + const originFetch = await git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.origin.fetch`, + }); + expect(originFetch).toBe(`+refs/heads/*:refs/remotes/origin/*`); + + await gitDDB.destroy(); + }); + + it('skip setting origin when it already exists.', async () => { + const remoteURL = remoteURLBase + commonId(); + + const dbNameA = serialId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await gitDDB.open(); + await gitDDB.sync(options); + + const remoteName = encodeToGitRemoteName(remoteURL); + + // Set origin + await git.setConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.origin.url`, + value: 'http://example.com/originurl', + }); + + const url = await git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.${remoteName}.url`, + }); + expect(url).toBe(remoteURL); + + const fetch = await git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.${encodeToGitRemoteName(remoteURL)}.fetch`, + }); + expect(fetch).toBe(`+refs/heads/*:refs/remotes/${remoteName}/*`); + + const originUrl = await git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `remote.origin.url`, + }); + expect(originUrl).toBe('http://example.com/originurl'); + + await gitDDB.destroy(); + }); + + it('calls tryPush() after create remote repository', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await gitDDB.open(); + const [sync, syncResult] = await gitDDB.sync(options, true); + + expect(syncResult).toMatchObject({ + action: 'push', + changes: { + remote: [ + { + new: { + _id: '.gitddb/info', + doc: { + creator: 'GitDocumentDB', + // dbId: '01FBTPJSX4AE871NA0QN3ZEQVF', + version: '1.0', + }, + // fileOid: 'e6d3f788687080d0fd1aa23cbc4f270f5a3f98d0', + name: '.gitddb/info.json', + type: 'json', + }, + operation: 'insert', + }, + ], + }, + }); + + await expect( + git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `branch.${gitDDB.defaultBranch}.remote`, + }) + ).resolves.toBe(sync.remoteName); + + await expect( + git.getConfig({ + fs, + dir: gitDDB.workingDir, + path: `branch.${gitDDB.defaultBranch}.merge`, + }) + ).resolves.toBe(`refs/heads/${gitDDB.defaultBranch}`); + + await gitDDB.destroy(); + }); + + it('retries tryPush() for 404 not found after create remote repository', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await gitDDB.open(); + + const sync = new Sync(gitDDB, options); + + const stubTryPush = sandbox.stub(sync, 'tryPush'); + stubTryPush.onCall(0).rejects(new RemoteErr.HTTPError404NotFound('')); + stubTryPush.onCall(1).rejects(new RemoteErr.HTTPError404NotFound('')); + stubTryPush.onCall(2).rejects(new RemoteErr.HTTPError404NotFound('')); + // @ts-ignore + stubTryPush.onCall(3).resolves({ action: 'push' }); + + const stubConfig = sandbox.stub(git, 'setConfig'); + stubConfig.returns(Promise.resolve()); + + const syncResult = await sync.init(); + + expect(syncResult).toMatchObject({ + action: 'push', + }); + + expect(stubTryPush.callCount).toBe(4); + + await gitDDB.destroy(); + }); + + it('retries tryPush() for 404 not found and throws after create remote repository', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await gitDDB.open(); + + const sync = new Sync(gitDDB, options); + + const stubTryPush = sandbox.stub(sync, 'tryPush'); + stubTryPush.onCall(0).rejects(new RemoteErr.HTTPError404NotFound('')); + stubTryPush.onCall(1).rejects(new RemoteErr.HTTPError404NotFound('')); + stubTryPush.onCall(2).rejects(new RemoteErr.HTTPError404NotFound('')); + // @ts-ignore + stubTryPush.onCall(3).rejects(new RemoteErr.HTTPError404NotFound('')); + + const stubConfig = sandbox.stub(git, 'setConfig'); + stubConfig.returns(Promise.resolve()); + + await expect(sync.init()).rejects.toThrowError(RemoteErr.HTTPError404NotFound); + + expect(stubTryPush.callCount).toBe(4); + + await gitDDB.destroy(); + }); + + it('succeeds when tryPush to updated repository', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir, + }); + await dbA.open(); + const optionA: RemoteOptions = { + remoteUrl: remoteURL, + syncDirection: 'push', + connection, + }; + await dbA.sync(optionA, true); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync({ + remoteUrl: remoteURL, + connection, + }); + await dbB.put({ name: 'fromB' }); + await syncB.tryPush(); + + await dbA.close(); + + await dbA.open(); + const [sync, result] = await dbA.sync(optionA, true); + expect(result).toEqual({ + action: 'nop', + }); + + await destroyDBs([dbA, dbB]); + }); + + it('succeeds when trySync to updated repository', async () => { + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + syncDirection: 'both', + connection, + } + ); + await dbB.put({ name: 'fromB' }); + await syncB.tryPush(); + + await dbA.close(); + await dbA.open(); + const [sync, syncResult] = await dbA.sync(syncB.options, true); + + expect(syncResult).toMatchObject({ + action: 'fast-forward merge', + }); + + await destroyDBs([dbA, dbB]); + }); + + it('throws PushNotAllowedError when syncDirection is pull', async () => { + const remoteURL = remoteURLBase + commonId(); + const dbName = serialId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await gitDDB.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + syncDirection: 'pull', + }; + const sync = new Sync(gitDDB, options); + await expect(sync.init()).resolves.toEqual({ action: 'nop' }); + + await gitDDB.destroy(); + }); + + it('After dbA created remote repository, dbB clones it.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + + await dbA.open(); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.sync(options); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + await dbB.sync(options); + + await expect(dbB.get(jsonA1._id)).resolves.toMatchObject(jsonA1); + + await destroyDBs([dbA, dbB]); + }); + + it('succeeds when a local repository does not exist and a remote repository does not exist.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + await expect(sync.trySync()).resolves.toMatchObject({ action: 'push' }); + + await destroyDBs([dbA]); + }); + + it('succeeds when a local repository does not exist and a remote empty repository exists.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + await createRemoteRepository(remoteURL); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const [sync, result] = await dbA.sync(options, true); + + expect(result).toMatchObject({ action: 'push' }); + + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + await expect(sync.trySync()).resolves.toMatchObject({ action: 'push' }); + + await destroyDBs([dbA]); + }); + + it('succeeds when a local repository does not exist and a remote fulfilled repository exists.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await sync.trySync(); + + // Destroy local DB + await dbA.destroy(); + + // Create it again + await dbA.open(); + const [sync_again, result] = await dbA.sync(options, true); + expect(result).toMatchObject({ action: 'combine database' }); + + await dbA.put(jsonA1); + await expect(sync_again.trySync()).resolves.toMatchObject({ action: 'push' }); + + await dbA.destroy(); + }); + + it('succeeds when a local repository exists and a remote repository does not exist.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const [sync, result] = await dbA.sync(options, true); + expect(result).toMatchObject({ action: 'push' }); + + const jsonA2 = { _id: '2', name: 'fromA' }; + await dbA.put(jsonA2); + await expect(sync.trySync()).resolves.toMatchObject({ action: 'push' }); + + await dbA.destroy(); + }); + + it('succeeds when a local repository exists and a remote empty repository exists.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + await createRemoteRepository(remoteURL); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const [sync, result] = await dbA.sync(options, true); + expect(result).toMatchObject({ action: 'push' }); + + const jsonA2 = { _id: '2', name: 'fromA' }; + await dbA.put(jsonA2); + await expect(sync.trySync()).resolves.toMatchObject({ action: 'push' }); + + await dbA.destroy(); + }); + + it('succeeds when a local repository exists and a remote consistent repository exists.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await sync.trySync(); + + // Close local DB + await dbA.close(); + + // Open it again + await dbA.open(); + + const [sync_again, result] = await dbA.sync(options, true); + expect(result).toMatchObject({ action: 'nop' }); + + await dbA.put(jsonA1); + await expect(sync_again.trySync()).resolves.toMatchObject({ action: 'push' }); + + await dbA.destroy(); + }); + + it('succeeds when a local repository exists and a remote inconsistent repository exists.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + const sync = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await sync.trySync(); + + // Destroy local DB + await dbA.destroy(); + + // Create another db + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + const [sync_again, result] = await dbB.sync(options, true); + expect(result).toMatchObject({ action: 'combine database' }); + + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + await expect(sync_again.trySync()).resolves.toMatchObject({ action: 'push' }); + + await dbB.destroy(); + }); + }); + + describe(' syncImpl()', () => { + it('throws RepositoryNotOpenError.', async () => { + const dbName = serialId(); + const remoteURL = remoteURLBase + commonId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + }); + await expect( + syncImpl.call(gitDDB, { + remoteUrl: remoteURL, + connection, + }) + ).rejects.toThrowError(Err.RepositoryNotOpenError); + await gitDDB.destroy(); + }); + }); + + it('Multiple Sync objects', async () => { + const gitDDB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await gitDDB.open(); + await gitDDB.put({ name: 'foo' }); + + const remoteOptions01: RemoteOptions = { + live: true, + remoteUrl: remoteURLBase + serialId(), + interval: 3000, + connection: { + type: 'github', + personalAccessToken: token, + }, + }; + + await gitDDB.sync(remoteOptions01); + + const remoteOptions02: RemoteOptions = { + live: true, + remoteUrl: remoteURLBase + serialId(), + interval: 3000, + connection: { + type: 'github', + personalAccessToken: token, + }, + }; + // Add extra synchronizer to DB + const sync02 = await gitDDB.sync(remoteOptions02); + expect(sync02).toBeInstanceOf(Sync); + + // Update remote from other DBs + const dbA = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbA.open(); + const syncA = await dbA.sync(remoteOptions01); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.trySync(); + + const dbB = new GitDocumentDB({ + dbName: serialId(), + localDir, + }); + await dbB.open(); + const syncB = await dbB.sync(remoteOptions02); + const jsonB2 = { _id: '2', name: 'fromB' }; + await dbB.put(jsonB2); + await syncB.trySync(); + + await sleep(remoteOptions01.interval! * 3); + + await expect(gitDDB.get('1')).resolves.toEqual(jsonA1); + await expect(gitDDB.get('2')).resolves.toEqual(jsonB2); + + await destroyDBs([gitDDB, dbA, dbB]); + }); +}; diff --git a/test/remote_base/sync_clone.ts b/test/remote_base/sync_clone.ts new file mode 100644 index 00000000..a4d7571d --- /dev/null +++ b/test/remote_base/sync_clone.ts @@ -0,0 +1,77 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test clone + * by using GitHub Personal Access Token + */ +import expect from 'expect'; +import { + createDatabase, + destroyDBs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { RemoteEngine } from '../../src/remote/remote_engine'; +import { ConnectionSettings } from '../../src/types'; + +export const syncCloneBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe(' clone', () => { + it('clones a repository', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const workingDir = localDir + '/' + dbNameB; + await RemoteEngine[syncA.engine].clone( + workingDir, + syncA.options, + 'origin', + dbA.tsLogger + ); + + const dbB = new GitDocumentDB({ localDir, dbName: dbNameB }); + await dbB.open(); + await expect(dbB.get(jsonA1._id)).resolves.toEqual(jsonA1); + + await destroyDBs([dbA, dbB]); + }); + }); +}; diff --git a/test/remote_base/sync_events.ts b/test/remote_base/sync_events.ts new file mode 100644 index 00000000..0d5c5106 --- /dev/null +++ b/test/remote_base/sync_events.ts @@ -0,0 +1,1289 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test synchronization events + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import expect from 'expect'; +import sinon from 'sinon'; +import { + ChangedFile, + ConnectionSettings, + RemoteOptions, + SyncResult, + SyncResultFastForwardMerge, + SyncResultMergeAndPush, + SyncResultPush, + TaskMetadata, +} from '../../src/types'; +import { sleep } from '../../src/utils'; +import { + compareWorkingDirAndBlobs, + createClonedDatabases, + createDatabase, + destroyDBs, + destroyRemoteRepository, + getChangedFileDelete, + getChangedFileInsert, + getChangedFileUpdate, + getCommitInfo, + getWorkingDirDocs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { RemoteErr } from '../../src/remote/remote_engine'; +import { Sync } from '../../src/remote/sync'; +import { MINIMUM_SYNC_INTERVAL } from '../../src/const'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pushWorker_module = require('../../src/remote/push_worker'); + +export const syncEventsBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + // Use sandbox to restore stub and spy in parallel mocha tests + let sandbox: sinon.SinonSandbox; + beforeEach(function () { + sandbox = sinon.createSandbox(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe(' [event]', () => { + /** + * Events + */ + describe('change', () => { + it('occurs once', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { connection } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B syncs + let result: SyncResultFastForwardMerge | undefined; + let changeTaskId = ''; + syncB.on('change', (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + result = syncResult as SyncResultFastForwardMerge; + changeTaskId = taskMetadata.taskId; + }); + let complete = false; + let endTaskId = ''; + syncB.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(result!.action).toBe('fast-forward merge'); + + expect(result!.commits).toMatchObject({ + local: getCommitInfo([putResult1]), + }); + + expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); + + expect(changeTaskId).toBe(endTaskId); + + await destroyDBs([dbA, dbB]); + }); + + it('is propagated between local and remote sites', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { connection } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.trySync(); + + // B puts and pushes + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + let resultA: SyncResultFastForwardMerge | undefined; + let completeA = false; + syncA.on('change', (syncResult: SyncResult) => { + resultA = syncResult as SyncResultFastForwardMerge; + console.log('A: ' + resultA.action); + if (resultA.action === 'fast-forward merge') { + completeA = true; + } + }); + + let resultB: SyncResultFastForwardMerge | undefined; + syncB.on('change', (syncResult: SyncResult) => { + resultB = syncResult as SyncResultFastForwardMerge; + console.log('B: ' + resultB.action); + }); + let completeB = false; + syncB.on('complete', () => { + completeB = true; + }); + + syncA.resume({ ...syncA.options, interval: 3000 }); + syncB.resume({ ...syncA.options, interval: 3000 }); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!completeA || !completeB) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(resultA!.action).toBe('fast-forward merge'); + + expect(resultA!.changes.local).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1), + ]); + + expect(resultB!.action).toBe('resolve conflicts and push'); + + expect(resultB!.changes.local).toEqual([]); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonB1]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonB1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 jsonA2 + * dbA : -jsonA1 -jsonA2 + * dbB : jsonB3 + * after : jsonB3 + */ + it('occurs with every retry', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + await dbA.put({ _id: '1' }); + await syncA.tryPush(); + + await dbB.put({ _id: '2' }); + + const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); + stubPush.onFirstCall().rejects(new RemoteErr.UnfetchedCommitExistsError('')); + + const resultsB: SyncResult[] = []; + syncB.on('change', (result: SyncResult) => { + if (resultsB.length === 0) { + // Restore stub after first change event. + stubPush.restore(); + } + // console.log('B: ' + JSON.stringify(result)); + resultsB.push(result); + }); + await syncB.trySync(); + + await sleep(syncA.options.retryInterval! + 5000); + expect(resultsB.length).toBe(2); + expect(resultsB[0].action).toBe('merge and push error'); + expect(resultsB[1].action).toBe('push'); + + await destroyDBs([dbA, dbB]); + }); + + it('is followed by localChange', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B syncs + let changes: ChangedFile[] = []; + let changeTaskId = ''; + syncB.on( + 'localChange', + (localChanges: ChangedFile[], taskMetadata: TaskMetadata) => { + changes = localChanges; + changeTaskId = taskMetadata.taskId; + } + ); + let complete = false; + let endTaskId = ''; + syncB.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(changes.length).toBe(1); + expect(changes).toEqual([getChangedFileInsert(jsonA1, putResult1)]); + + expect(changeTaskId).toBe(endTaskId); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 jsonA2 + * dbA : -jsonA1 -jsonA2 + * dbB : jsonB3 + * after : jsonB3 + */ + it('occurs localChanges when SyncResultMergeAndPushError', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + await dbA.put({ _id: '1' }); + await syncA.tryPush(); + + await dbB.put({ _id: '2' }); + + const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); + stubPush.onFirstCall().rejects(new RemoteErr.UnfetchedCommitExistsError('')); + + const localChangesB: ChangedFile[][] = []; + syncB.on('localChange', (changes: ChangedFile[]) => { + if (localChangesB.length === 0) { + // Restore stub after first change event. + stubPush.restore(); + } + localChangesB.push(changes); + }); + + await syncB.trySync(); + + await sleep(syncB.options.retryInterval! + 5000); + expect(localChangesB.length).toBe(1); + + await syncB.trySync(); + }); + + it('is followed by remoteChange', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + let changes: ChangedFile[] = []; + let changeTaskId = ''; + syncB.on( + 'remoteChange', + (remoteChanges: ChangedFile[], taskMetadata: TaskMetadata) => { + changes = remoteChanges; + changeTaskId = taskMetadata.taskId; + } + ); + let complete = false; + let endTaskId = ''; + syncB.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + + // B puts and syncs + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResult1 = await dbB.put(jsonB1); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(changes.length).toBe(1); + + expect(changes).toEqual([getChangedFileInsert(jsonB1, putResult1)]); + + expect(changeTaskId).toBe(endTaskId); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 jsonA2 + * dbA : -jsonA1 -jsonA2 + * dbB : jsonB3 + * after : jsonB3 + */ + it('occurs remoteChanges after SyncResultMergeAndPushError', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + await dbA.put({ _id: '1' }); + await syncA.tryPush(); + + await dbB.put({ _id: '2' }); + + const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); + stubPush.onFirstCall().rejects(new RemoteErr.UnfetchedCommitExistsError('')); + + let firstChange = true; + syncB.on('change', (changes: ChangedFile[]) => { + if (firstChange) { + firstChange = false; + // Restore stub after first change event. + stubPush.restore(); + } + }); + const remoteChangesB: ChangedFile[][] = []; + syncB.on('remoteChange', (changes: ChangedFile[]) => { + remoteChangesB.push(changes); + }); + + await syncB.trySync(); + + await sleep(syncB.options.retryInterval! + 5000); + expect(remoteChangesB.length).toBe(1); + + await syncB.trySync(); + }); + }); + + describe('filtered by collectionPath', () => { + it('occurs change and localChange events', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const col01 = dbA.collection('col01'); + const col02 = dbA.collection('col02'); + const jsonA1 = { _id: '1', name: 'fromA' }; + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult1 = await col01.put(jsonA1); + const putResult2 = await col02.put(jsonA2); + + const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; + const putResult1dash = { ...putResult1, _id: 'col01/1' }; + const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; + const putResult2dash = { ...putResult2, _id: 'col02/2' }; + + await syncA.tryPush(); + + // B syncs + let col01Result: SyncResultFastForwardMerge | undefined; + let col01ChangeTaskId: string | undefined; + syncB.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + col01Result = syncResult as SyncResultFastForwardMerge; + col01ChangeTaskId = taskMetadata.taskId; + }, + 'col01' + ); + + let changedFiles: ChangedFile[]; + syncB.on( + 'localChange', + (files: ChangedFile[], taskMetadata: TaskMetadata) => { + changedFiles = files; + }, + 'col02' + ); + + let rootResult: SyncResultFastForwardMerge | undefined; + let rootChangeTaskId: string | undefined; + syncB.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + rootResult = syncResult as SyncResultFastForwardMerge; + rootChangeTaskId = taskMetadata.taskId; + }, + '' + ); + + let complete = false; + let endTaskId = ''; + let completeCollectionPath: string | undefined; + syncB.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + completeCollectionPath = taskMetadata.collectionPath; + }); + await syncB.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(col01Result?.action).toBe('fast-forward merge'); + expect(rootResult?.action).toBe('fast-forward merge'); + + expect(col01Result?.commits).toMatchObject({ + local: getCommitInfo([putResult1, putResult2]), + }); + expect(rootResult?.commits).toMatchObject({ + local: getCommitInfo([putResult1, putResult2]), + }); + + expect(col01Result?.changes.local).toEqual([ + getChangedFileInsert(jsonA1, putResult1), + ]); + expect(changedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); + + expect(rootResult?.changes.local).toEqual([ + getChangedFileInsert(jsonA1dash, putResult1dash), + getChangedFileInsert(jsonA2dash, putResult2dash), + ]); + + expect(col01ChangeTaskId).toBe(endTaskId); + expect(rootChangeTaskId).toBe(endTaskId); + + expect(completeCollectionPath).toBe(''); + + await destroyDBs([dbA, dbB]); + }); + + it('occurs change events with update and delete', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const col01 = dbA.collection('col01'); + const col02 = dbA.collection('col02'); + const jsonA1 = { _id: '1', name: 'fromA' }; + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult1 = await col01.put(jsonA1); + await col02.put(jsonA2); + await syncA.trySync(); + const jsonA1updated = { _id: '1', name: 'updated' }; + const putResult1updated = await col01.put(jsonA1updated); + const deleteResult2 = await col02.delete(jsonA2); + + let col01Result: SyncResultPush | undefined; + let col01ChangeTaskId: string | undefined; + syncA.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + col01Result = syncResult as SyncResultPush; + col01ChangeTaskId = taskMetadata.taskId; + }, + 'col01' + ); + + let changedFiles: ChangedFile[]; + syncA.on( + 'remoteChange', + (files: ChangedFile[], taskMetadata: TaskMetadata) => { + changedFiles = files; + }, + 'col02' + ); + + let complete = false; + syncA.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + }); + await syncA.tryPush(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(col01Result?.action).toBe('push'); + + expect(col01Result?.commits).toMatchObject({ + remote: getCommitInfo([putResult1updated, deleteResult2]), + }); + + expect(col01Result?.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResult1, jsonA1updated, putResult1updated), + ]); + expect(changedFiles!).toEqual([getChangedFileDelete(jsonA2, deleteResult2)]); + + await destroyDBs([dbA, dbB]); + }); + + it('occurs change and remoteChange events by trySync', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const col01 = dbA.collection('col01'); + const col02 = dbA.collection('col02'); + const jsonA1 = { _id: '1', name: 'fromA' }; + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult1 = await col01.put(jsonA1); + const putResult2 = await col02.put(jsonA2); + + const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; + const putResult1dash = { ...putResult1, _id: 'col01/1' }; + const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; + const putResult2dash = { ...putResult2, _id: 'col02/2' }; + + let col01Result: SyncResultPush | undefined; + let col01ChangeTaskId: string | undefined; + syncA.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + col01Result = syncResult as SyncResultPush; + col01ChangeTaskId = taskMetadata.taskId; + }, + 'col01' + ); + + let changedFiles: ChangedFile[]; + syncA.on( + 'remoteChange', + (files: ChangedFile[], taskMetadata: TaskMetadata) => { + changedFiles = files; + }, + 'col02' + ); + + let rootResult: SyncResultPush | undefined; + let rootChangeTaskId: string | undefined; + syncA.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + rootResult = syncResult as SyncResultPush; + rootChangeTaskId = taskMetadata.taskId; + }, + '' + ); + + let complete = false; + let endTaskId = ''; + let completeCollectionPath: string | undefined; + syncA.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + completeCollectionPath = taskMetadata.collectionPath; + }); + await syncA.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(col01Result?.action).toBe('push'); + expect(rootResult?.action).toBe('push'); + + expect(col01Result?.commits).toMatchObject({ + remote: getCommitInfo([putResult1, putResult2]), + }); + expect(rootResult?.commits).toMatchObject({ + remote: getCommitInfo([putResult1, putResult2]), + }); + + expect(col01Result?.changes.remote).toEqual([ + getChangedFileInsert(jsonA1, putResult1), + ]); + expect(changedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); + + expect(rootResult?.changes.remote).toEqual([ + getChangedFileInsert(jsonA1dash, putResult1dash), + getChangedFileInsert(jsonA2dash, putResult2dash), + ]); + + expect(col01ChangeTaskId).toBe(endTaskId); + expect(rootChangeTaskId).toBe(endTaskId); + + expect(completeCollectionPath).toBe(''); + + await destroyDBs([dbA, dbB]); + }); + + it('occurs change and remoteChange events by tryPush', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const col01 = dbA.collection('col01'); + const col02 = dbA.collection('col02'); + const jsonA1 = { _id: '1', name: 'fromA' }; + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult1 = await col01.put(jsonA1); + const putResult2 = await col02.put(jsonA2); + + const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; + const putResult1dash = { ...putResult1, _id: 'col01/1' }; + const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; + const putResult2dash = { ...putResult2, _id: 'col02/2' }; + + let col01Result: SyncResultPush | undefined; + let col01ChangeTaskId: string | undefined; + syncA.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + col01Result = syncResult as SyncResultPush; + col01ChangeTaskId = taskMetadata.taskId; + }, + 'col01' + ); + + let changedFiles: ChangedFile[]; + syncA.on( + 'remoteChange', + (files: ChangedFile[], taskMetadata: TaskMetadata) => { + changedFiles = files; + }, + 'col02' + ); + + let rootResult: SyncResultPush | undefined; + let rootChangeTaskId: string | undefined; + syncA.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + rootResult = syncResult as SyncResultPush; + rootChangeTaskId = taskMetadata.taskId; + }, + '' + ); + + let complete = false; + let endTaskId = ''; + let completeCollectionPath: string | undefined; + syncA.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + completeCollectionPath = taskMetadata.collectionPath; + }); + await syncA.tryPush(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(col01Result?.action).toBe('push'); + expect(rootResult?.action).toBe('push'); + + expect(col01Result?.commits).toMatchObject({ + remote: getCommitInfo([putResult1, putResult2]), + }); + expect(rootResult?.commits).toMatchObject({ + remote: getCommitInfo([putResult1, putResult2]), + }); + + expect(col01Result?.changes.remote).toEqual([ + getChangedFileInsert(jsonA1, putResult1), + ]); + expect(changedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); + + expect(rootResult?.changes.remote).toEqual([ + getChangedFileInsert(jsonA1dash, putResult1dash), + getChangedFileInsert(jsonA2dash, putResult2dash), + ]); + + expect(col01ChangeTaskId).toBe(endTaskId); + expect(rootChangeTaskId).toBe(endTaskId); + + expect(completeCollectionPath).toBe(''); + + await destroyDBs([dbA, dbB]); + }); + + it('occurs change, localChange, and remoteChange events by merge and push', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const col01 = dbA.collection('col01'); + const col02 = dbA.collection('col02'); + const jsonA1 = { _id: '1', name: 'fromA' }; + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult1 = await col01.put(jsonA1); + const putResult2 = await col02.put(jsonA2); + + const jsonA1dash = { _id: 'col01/1', name: 'fromA' }; + const putResult1dash = { ...putResult1, _id: 'col01/1' }; + const jsonA2dash = { _id: 'col02/2', name: 'fromA' }; + const putResult2dash = { ...putResult2, _id: 'col02/2' }; + + const jsonB3 = { _id: '3', name: 'fromB' }; + const putResult3 = await dbB.collection('col01').put(jsonB3); + const jsonB3dash = { _id: 'col01/3', name: 'fromB' }; + const putResult3dash = { ...putResult3, _id: 'col01/3' }; + await syncB.trySync(); + + let col01Result: SyncResultMergeAndPush | undefined; + let col01ChangeTaskId: string | undefined; + syncA.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + col01Result = syncResult as SyncResultMergeAndPush; + col01ChangeTaskId = taskMetadata.taskId; + }, + 'col01' + ); + + let localChangedFiles: ChangedFile[]; + syncA.on( + 'localChange', + (files: ChangedFile[], taskMetadata: TaskMetadata) => { + localChangedFiles = files; + }, + 'col01' + ); + + let remoteChangedFiles: ChangedFile[]; + syncA.on( + 'remoteChange', + (files: ChangedFile[], taskMetadata: TaskMetadata) => { + remoteChangedFiles = files; + }, + 'col02' + ); + + let rootResult: SyncResultMergeAndPush | undefined; + let rootChangeTaskId: string | undefined; + syncA.on( + 'change', + (syncResult: SyncResult, taskMetadata: TaskMetadata) => { + rootResult = syncResult as SyncResultMergeAndPush; + rootChangeTaskId = taskMetadata.taskId; + }, + '' + ); + + let complete = false; + let endTaskId = ''; + let completeCollectionPath: string | undefined; + syncA.on( + 'complete', + (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + completeCollectionPath = taskMetadata.collectionPath; + }, + 'col01' + ); + await syncA.trySync(); + + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + } + + expect(col01Result?.action).toBe('merge and push'); + expect(rootResult?.action).toBe('merge and push'); + + expect(col01Result?.commits).toMatchObject({ + remote: getCommitInfo([putResult1, putResult2, 'merge']), + local: getCommitInfo([putResult3, 'merge']), + }); + expect(rootResult?.commits).toMatchObject({ + remote: getCommitInfo([putResult1, putResult2, 'merge']), + local: getCommitInfo([putResult3, 'merge']), + }); + + expect(col01Result?.changes.remote).toEqual([ + getChangedFileInsert(jsonA1, putResult1), + ]); + expect(col01Result?.changes.local).toEqual([ + getChangedFileInsert(jsonB3, putResult3), + ]); + expect(localChangedFiles!).toEqual([getChangedFileInsert(jsonB3, putResult3)]); + expect(remoteChangedFiles!).toEqual([getChangedFileInsert(jsonA2, putResult2)]); + + expect(rootResult?.changes.remote).toEqual([ + getChangedFileInsert(jsonA1dash, putResult1dash), + getChangedFileInsert(jsonA2dash, putResult2dash), + ]); + expect(rootResult?.changes.local).toEqual([ + getChangedFileInsert(jsonB3dash, putResult3dash), + ]); + + expect(col01ChangeTaskId).toBe(endTaskId); + expect(rootChangeTaskId).toBe(endTaskId); + + expect(completeCollectionPath).toBe('col01/'); + + await destroyDBs([dbA, dbB]); + }); + }); + + it('pause and resume', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + includeCommits: true, + live: true, + interval: 3000, + } + ); + + let resume = false; + syncB.on('resume', () => { + resume = true; + }); + let pause = false; + syncB.on('pause', () => { + pause = true; + }); + let complete = false; + syncB.on('complete', () => { + complete = true; + }); + + // Check first complete event + + let sleepTime = 0; + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + sleepTime += 1000; + } + + syncB.pause(); + expect(pause).toBe(true); + expect(resume).toBe(false); + expect(syncB.options.live).toBe(false); + + // Check second complete event + complete = false; // reset + // fast forward timer + await sleep(sleepTime + 1000); + + expect(complete).toBe(false); // complete will not happen because synchronization is paused. + + syncB.resume(); + expect(resume).toBe(true); + expect(syncB.options.live).toBe(true); + + // Check third complete event + complete = false; // reset + // fast forward timer + await sleep(sleepTime + 1000); + + expect(complete).toBe(true); + + await destroyDBs([dbA, dbB]); + }); + + it('active at initialization', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + includeCommits: true, + live: true, + }; + await dbA.open(); + + const sync = new Sync(dbA, options); + let resume = false; + sync.on('resume', () => { + resume = true; + }); + + const syncResult = await sync.init(); + console.log(JSON.stringify(syncResult)); + expect(resume).toBe(true); + + sync.close(); + + await destroyDBs([dbA]); + }); + + it('starts once', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + includeCommits: true, + live: true, + interval: 3000, + } + ); + + let start = false; + syncA.on('start', () => { + start = true; + }); + + expect(start).toBe(false); + + let sleepTime = 0; + // eslint-disable-next-line no-unmodified-loop-condition + while (!start) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + sleepTime += 1000; + } + + expect(start).toBe(true); + expect(sleepTime).toBeLessThan(5000); + + await destroyDBs([dbA]); + }); + + it('starts repeatedly', async () => { + const interval = MINIMUM_SYNC_INTERVAL; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + includeCommits: true, + live: true, + interval, + } + ); + + let counter = 0; + syncA.on('start', () => { + counter++; + }); + + await sleep(interval * 5); + + expect(counter).toBeGreaterThanOrEqual(3); + + await destroyDBs([dbA]); + }); + + it('starts event returns taskMetaData and current retries', async () => { + const interval = MINIMUM_SYNC_INTERVAL; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + includeCommits: true, + live: true, + interval, + } + ); + + let counter = 0; + let taskId = ''; + let currentRetries = -1; + syncA.on('start', (taskMetadata: TaskMetadata, _currentRetries: number) => { + counter++; + taskId = taskMetadata.taskId; + currentRetries = _currentRetries; + }); + + await sleep(interval * 5); + + expect(counter).toBeGreaterThanOrEqual(3); + expect(taskId).not.toBe(''); + expect(currentRetries).toBe(0); + + await destroyDBs([dbA]); + }); + + it('completes once', async () => { + const interval = MINIMUM_SYNC_INTERVAL; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + includeCommits: true, + live: true, + interval, + } + ); + + let startTaskId = ''; + syncA.on('start', (taskMetadata: TaskMetadata) => { + startTaskId = taskMetadata.taskId; + }); + + let complete = false; + let endTaskId = ''; + syncA.on('complete', (taskMetadata: TaskMetadata) => { + complete = true; + endTaskId = taskMetadata.taskId; + }); + + expect(complete).toBe(false); + + let sleepTime = 0; + // eslint-disable-next-line no-unmodified-loop-condition + while (!complete) { + // eslint-disable-next-line no-await-in-loop + await sleep(700); + sleepTime += 700; + } + + expect(complete).toBe(true); + expect(startTaskId).toBe(endTaskId); + expect(sleepTime).toBeLessThan(interval * 2); + + await destroyDBs([dbA]); + }); + + it('completes repeatedly', async () => { + const interval = MINIMUM_SYNC_INTERVAL; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + includeCommits: true, + live: true, + interval, + } + ); + + let counter = 0; + syncA.on('complete', () => { + counter++; + }); + + await sleep(interval * 5); + + expect(counter).toBeGreaterThanOrEqual(3); + + await destroyDBs([dbA]); + }); + + it('error', async () => { + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + serialId, + { + connection, + } + ); + await dbA.put({ _id: '1', name: 'fromA' }); + await syncA.trySync(); + + await destroyRemoteRepository(syncA.remoteURL); + // Create different repository with the same repository name. + const [dbB, syncB] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + await dbB.put({ _id: '1', name: 'fromB' }); + await syncB.trySync(); + + let startTaskId = ''; + syncA.on('start', (taskMetadata: TaskMetadata) => { + startTaskId = taskMetadata.taskId; + }); + + let error = false; + let errorTaskId = ''; + syncA.on('error', (e: Error, taskMetadata: TaskMetadata) => { + error = true; + errorTaskId = taskMetadata.taskId; + }); + await expect(syncA.trySync()).rejects.toThrowError(RemoteErr.HTTPError404NotFound); + + expect(error).toBe(true); + expect(startTaskId).toBe(errorTaskId); + + error = false; + await expect(syncA.tryPush()).rejects.toThrowError(); // request failed with status code: 404 + + expect(error).toBe(true); + + await destroyDBs([dbA, dbB]); + }); + + it('on and off', async () => { + const interval = MINIMUM_SYNC_INTERVAL; + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + includeCommits: true, + live: true, + interval, + } + ); + + let counter = 0; + const increment = () => { + counter++; + }; + syncA.on('start', increment); + + await sleep(interval * 3); + + expect(counter).toBeGreaterThanOrEqual(1); + expect(counter).toBeLessThanOrEqual(3); + + syncA.off('start', increment); + + await sleep(interval * 3); + + expect(counter).toBeLessThanOrEqual(3); + + await destroyDBs([dbA]); + }); + }); +}; diff --git a/test/remote/sync_github_noauth.test.ts b/test/remote_base/sync_github_noauth.test.ts similarity index 100% rename from test/remote/sync_github_noauth.test.ts rename to test/remote_base/sync_github_noauth.test.ts diff --git a/test/remote/sync_github_nopat_nooauth_sshkey.test.ts b/test/remote_base/sync_github_nopat_nooauth_sshkey.test.ts similarity index 100% rename from test/remote/sync_github_nopat_nooauth_sshkey.test.ts rename to test/remote_base/sync_github_nopat_nooauth_sshkey.test.ts diff --git a/test/remote/sync_github_nopat_oauth.test.ts b/test/remote_base/sync_github_nopat_oauth.test.ts similarity index 100% rename from test/remote/sync_github_nopat_oauth.test.ts rename to test/remote_base/sync_github_nopat_oauth.test.ts diff --git a/test/remote_base/sync_live.ts b/test/remote_base/sync_live.ts new file mode 100644 index 00000000..753eded2 --- /dev/null +++ b/test/remote_base/sync_live.ts @@ -0,0 +1,369 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test lifecycle of synchronization (open, sync, tryPush, trySync) + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import expect from 'expect'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { ConnectionSettings, RemoteOptions } from '../../src/types'; +import { sleep } from '../../src/utils'; +import { destroyDBs, removeRemoteRepositories } from '../remote_utils'; +import { MINIMUM_SYNC_INTERVAL } from '../../src/const'; + +export const syncLiveBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + /** + * Test periodic Sync (live) + */ + + describe(' periodic Sync', () => { + it('starts and pushes after interval when called from open() with live option.', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + expect(syncA.options.live).toBeTruthy(); + expect(syncA.options.interval).toBe(interval); + + // Wait live sync() + while (dbA.taskQueue.currentStatistics().sync === 0) { + // eslint-disable-next-line no-await-in-loop + await sleep(500); + } + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + await dbB.sync(options); + await expect(dbB.get(jsonA1._id)).resolves.toMatchObject(jsonA1); + + await destroyDBs([dbA, dbB]); + }); + + it('stops by pause()', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + + expect(syncA.options.live).toBeTruthy(); + const count = dbA.taskQueue.currentStatistics().sync; + syncA.pause(); + await sleep(interval * 2); + expect(syncA.options.live).toBeFalsy(); + expect(dbA.taskQueue.currentStatistics().sync).toBe(count); + + await destroyDBs([dbA]); + }); + + it('pause() and resume()', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + logLevel: 'silly', + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + expect(syncA.options.live).toBeTruthy(); + const count = dbA.taskQueue.currentStatistics().sync; + expect(syncA.pause()).toBeTruthy(); + expect(syncA.pause()).toBeFalsy(); // ignored + + await sleep(interval * 2); + expect(syncA.options.live).toBeFalsy(); + expect(dbA.taskQueue.currentStatistics().sync).toBe(count); + + expect(syncA.resume()).toBeTruthy(); + expect(syncA.resume()).toBeFalsy(); // ignored + await sleep(interval * 2); + expect(syncA.options.live).toBeTruthy(); + expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThan(count); + + await destroyDBs([dbA]); + }); + + it('stops by gitDDB.close()', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + + expect(syncA.options.live).toBeTruthy(); + const count = dbA.taskQueue.currentStatistics().sync; + await dbA.close(); + + syncA.resume(); // resume() must be ignored after close(); + + await sleep(interval * 2); + expect(syncA.options.live).toBeFalsy(); + expect(dbA.taskQueue.currentStatistics().sync).toBe(count); + + await destroyDBs([dbA]); + }); + + it('changes interval when resume() is called with new interval.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + + expect(syncA.options.interval).toBe(interval); + + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + // Wait live sync() + while (dbA.taskQueue.currentStatistics().sync === 0) { + // eslint-disable-next-line no-await-in-loop + await sleep(500); + } + syncA.pause(); + + const jsonA2 = { _id: '2', name: 'fromA' }; + await dbA.put(jsonA2); + + const currentCount = dbA.taskQueue.currentStatistics().sync; + // Change interval + syncA.resume({ + interval: interval * 3, + }); + expect(syncA.options.interval).toBe(interval * 3); + await sleep(interval); + // Check count before next sync() + expect(dbA.taskQueue.currentStatistics().sync).toBe(currentCount); + + await destroyDBs([dbA]); + }); + + it('repeats tryPush() automatically.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'push', + interval, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + syncA.on('error', (err: Error) => { + console.log(err); + }); + await sleep(interval * 5); + expect(dbA.taskQueue.currentStatistics().push).toBeGreaterThanOrEqual(3); + + await destroyDBs([dbA]); + }); + + it('repeats trySync() automatically.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + syncA.on('error', (err: Error) => { + console.log(err); + }); + await sleep(interval * 5); + expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThanOrEqual(3); + + await destroyDBs([dbA]); + }); + + it('skips pushWorker after pause.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'push', + interval: 1000000, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + syncA.pause(); + await expect(syncA.tryPushImpl(true)).resolves.toEqual({ action: 'canceled' }); + syncA.resume(); + await expect(syncA.tryPushImpl(true)).resolves.toMatchObject({ action: 'nop' }); + + await destroyDBs([dbA]); + }); + + it('skips syncWorker after pause.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval: 1000000, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + syncA.pause(); + await expect(syncA.trySyncImpl(true)).resolves.toEqual({ action: 'canceled' }); + syncA.resume(); + await expect(syncA.trySyncImpl(true)).resolves.toMatchObject({ action: 'nop' }); + + await destroyDBs([dbA]); + }); + + it('runBeforeLiveSync', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const interval = MINIMUM_SYNC_INTERVAL; + const options: RemoteOptions = { + remoteUrl: remoteURL, + live: true, + syncDirection: 'both', + interval, + connection, + }; + await dbA.open(); + const executed: number[] = []; + const syncA = await dbA.sync(options); + syncA.runBeforeLiveSync = () => { + executed.push(0); + }; + syncA.on('start', () => { + executed.push(1); + }); + syncA.on('error', (err: Error) => { + console.log(err); + }); + + await sleep(interval * 5); + executed.length = 6; + expect(JSON.stringify(executed)).toBe('[0,1,0,1,0,1]'); + + await destroyDBs([dbA]); + }); + }); +}; diff --git a/test/remote_base/sync_trypush.ts b/test/remote_base/sync_trypush.ts new file mode 100644 index 00000000..a09902be --- /dev/null +++ b/test/remote_base/sync_trypush.ts @@ -0,0 +1,661 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test push + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import expect from 'expect'; +import sinon from 'sinon'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { + compareWorkingDirAndBlobs, + createDatabase, + destroyDBs, + getChangedFileDelete, + getChangedFileInsert, + getChangedFileUpdate, + getCommitInfo, + getWorkingDirDocs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { + ConnectionSettings, + ConnectionSettingsGitHub, + RemoteOptions, + SyncResultCancel, + SyncResultNop, + SyncResultPush, +} from '../../src/types'; +import { sleep } from '../../src/utils'; +import { RemoteEngine, RemoteErr } from '../../src/remote/remote_engine'; + +export const syncTryPushBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + // Use sandbox to restore stub and spy in parallel mocha tests + let sandbox: sinon.SinonSandbox; + beforeEach(function () { + // To avoid secondary rate limit of GitHub + // await new Promise(resolve => setTimeout(resolve, 3000)); + + sandbox = sinon.createSandbox(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe(': Sync#tryPush()', () => { + /** + * before: + * dbA : +jsonA1 + * after : jsonA1 + */ + it('changes one remote insertion when pushes after one put()', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // Put and push + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult = await dbA.put(jsonA1); + const syncResult = await syncA.tryPush(); + expect(syncResult.action).toBe('push'); + if (syncResult.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + expect(syncResult.commits).toMatchObject({ + remote: getCommitInfo([putResult]), + }); + + // One remote creation + expect(syncResult.changes.remote.length).toBe(1); + expect(syncResult.changes.remote).toEqual([getChangedFileInsert(jsonA1, putResult)]); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * after : jsonA1 + */ + it('does not change remote when pushes after put() the same document again', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + // This document is same as the previous document + // while put() creates a new commit. + // (This is valid behavior of put() API.) + const putResult = await dbA.put(jsonA1); + const syncResult = await syncA.tryPush(); + expect(syncResult.action).toBe('push'); + if (syncResult.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + + expect(syncResult.commits).toMatchObject({ + remote: getCommitInfo([putResult]), + }); + + // Does not change remote + expect(syncResult.changes.remote.length).toBe(0); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * after : jsonA1 + */ + it('changes one remote update when pushes after put() updated document', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // Put and push an updated document + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResult = await dbA.put(jsonA1dash); + const syncResult = await syncA.tryPush(); + expect(syncResult.action).toBe('push'); + if (syncResult.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + + expect(syncResult.commits).toMatchObject({ + remote: getCommitInfo([putResult]), + }); + + // One remote update + expect(syncResult.changes.remote.length).toBe(1); + expect(syncResult.changes.remote[0]).toMatchObject( + getChangedFileUpdate(jsonA1, putResultA1, jsonA1dash, putResult) + ); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA2 + * after : jsonA1 jsonA2 + */ + it('changes one remote insertion when pushes after put() another document', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + // Put and push another document + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + const syncResult = await syncA.tryPush(); + expect(syncResult.action).toBe('push'); + if (syncResult.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + + expect(syncResult.commits).toMatchObject({ + remote: getCommitInfo([putResultA2]), + }); + + // One remote creation + expect(syncResult.changes.remote.length).toBe(1); + expect(syncResult.changes.remote[0]).toMatchObject( + getChangedFileInsert(jsonA2, putResultA2) + ); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: + * dbA : +jsonA1 +jsonA2 + * after1: jsonA1 jsonA2 + * dbA : +jsonA1 +jsonA3 + * after2: jsonA1 jsonA2 jsonA3 + */ + it('changes two remote insertions when pushes after put() two documents', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // Two put commands and push + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult2 = await dbA.put(jsonA2); + const syncResult = await syncA.tryPush(); + expect(syncResult.action).toBe('push'); + if (syncResult.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + + expect(syncResult.commits).toMatchObject({ + remote: getCommitInfo([putResult1, putResult2]), + }); + + // Two remote creations + expect(syncResult.changes.remote.length).toBe(2); + expect(syncResult.changes.remote).toEqual([ + getChangedFileInsert(jsonA1, putResult1), + getChangedFileInsert(jsonA2, putResult2), + ]); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 jsonA2 + * after : +jsonA1 jsonA2 + */ + it('changes one remote insertion and one remote update when pushes after put() updated document and another document', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResult1dash = await dbA.put(jsonA1dash); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult2 = await dbA.put(jsonA2); + const syncResult = await syncA.tryPush(); + expect(syncResult.action).toBe('push'); + if (syncResult.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + + expect(syncResult.commits).toMatchObject({ + remote: getCommitInfo([putResult1dash, putResult2]), + }); + + // One remote update and one remote creation + expect(syncResult.changes.remote.length).toBe(2); + expect(syncResult.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResult1, jsonA1dash, putResult1dash), + getChangedFileInsert(jsonA2, putResult2), + ]); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: jsonA1 + * dbA : -jsonA1 + * after : + */ + it('changes one remote delete when pushes after one delete()', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + const deleteResult1 = await dbA.delete(jsonA1); + + const syncResult1 = await syncA.tryPush(); + expect(syncResult1.action).toBe('push'); + if (syncResult1.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + + expect(syncResult1.commits).toMatchObject({ + remote: getCommitInfo([deleteResult1]), + }); + + // One remote delete + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileDelete(jsonA1, deleteResult1), + ]); + + expect(getWorkingDirDocs(dbA)).toEqual([]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: + * dbA : +jsonA1 + * dbA : -jsonA1 + * after : + */ + it('does not change remote when pushes after put() and delete()', async function () { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const jsonA1 = { _id: '1', name: 'fromA' }; + // Put and delete the same document + const putResult1 = await dbA.put(jsonA1); + const deleteResult1 = await dbA.delete(jsonA1); + + const syncResult1 = await syncA.tryPush(); + expect(syncResult1.action).toBe('push'); + if (syncResult1.action !== 'push') { + // Check discriminated union + throw new Error('invalid result'); + } + + expect(syncResult1.commits).toMatchObject({ + remote: getCommitInfo([putResult1, deleteResult1]), + }); + + // Does not change remote + expect(syncResult1.changes.remote.length).toBe(0); + + expect(getWorkingDirDocs(dbA)).toEqual([]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + it('returns SyncResultNop when local does not have ahead commits.', async () => { + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + await expect(syncA.tryPush()).resolves.toEqual({ action: 'nop' }); + + await destroyDBs([dbA]); + }); + + it('skips consecutive push tasks', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + const results: (SyncResultPush | SyncResultCancel | SyncResultNop)[] = []; + for (let i = 0; i < 10; i++) { + // eslint-disable-next-line promise/catch-or-return + syncA.tryPush().then(result => results.push(result)); + } + await sleep(5000); + + const syncResultCancel: SyncResultCancel = { + action: 'canceled', + }; + // results will be include 7 or more cancels + let cancelCount = 0; + results.forEach(res => { + if (res.action === 'canceled') cancelCount++; + }); + expect(cancelCount).toBeGreaterThan(6); + + // 3 or less tryPushes will be executed + expect(dbA.taskQueue.currentStatistics().push).toBeLessThanOrEqual(3); + + await destroyDBs([dbA]); + }); + + it('pauses live push after error', async () => { + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + serialId, + { + connection, + live: true, + interval: 3000, + syncDirection: 'push', + } + ); + expect(syncA.options.live).toBeTruthy(); + + dbA.put({ name: 'fromA' }); + + let error: Error | undefined; + syncA.on('error', (err: Error) => { + error = err; + }); + const stubPush = sandbox.stub(RemoteEngine[syncA.engine], 'push'); + stubPush.onFirstCall().throwsException(new RemoteErr.NetworkError('foo')); + + for (let i = 0; i < 10; i++) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + if (error instanceof Error) { + break; + } + } + + expect(error).toBeInstanceOf(RemoteErr.NetworkError); + // expect(syncA.options.live).toBeFalsy(); + + await destroyDBs([dbA]); + }); + + it('Race condition of two tryPush() calls throws UnfetchedCommitExistsError.', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + const syncB = await dbB.sync(options); + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + await expect(Promise.all([syncA.tryPush(), syncB.tryPush()])).rejects.toThrowError( + RemoteErr.UnfetchedCommitExistsError + ); + + await destroyDBs([dbA, dbB]); + }); + + it('Ordered condition of two tryPush() calls throws UnfetchedCommitExistsError.', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + const syncB = await dbB.sync(options); + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + await syncA.tryPush(); + await expect(syncB.tryPush()).rejects.toThrowError( + RemoteErr.UnfetchedCommitExistsError + ); + + await destroyDBs([dbA, dbB]); + }); + + it('pushes some commits. All commits can be cloned.', async () => { + const remoteURL = remoteURLBase + serialId(); + + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir, + }); + const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + const options = { + remoteUrl: remoteURL, + connection, + includeCommits: true, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + + const jsonA1 = { _id: 'A1' }; + const jsonA2 = { _id: 'A2' }; + const jsonA3 = { _id: 'A3' }; + const jsonA4 = { _id: 'A4' }; + const jsonA5 = { _id: 'A5' }; + const jsonA6 = { _id: 'A6' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + await dbA.put(jsonA2); + await dbA.put(jsonA3); + await syncA.tryPush(); + + await dbA.put(jsonA4); + await dbA.put(jsonA5); + await dbA.put(jsonA6); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + await dbB.sync(options); + await expect(dbB.get('A1')).resolves.toEqual(jsonA1); + await expect(dbB.get('A2')).resolves.toEqual(jsonA2); + await expect(dbB.get('A3')).resolves.toEqual(jsonA3); + await expect(dbB.get('A4')).resolves.toEqual(jsonA4); + await expect(dbB.get('A5')).resolves.toEqual(jsonA5); + await expect(dbB.get('A6')).resolves.toEqual(jsonA6); + await destroyDBs([dbA, dbB]); + }); + }); +}; diff --git a/test/remote_base/sync_trysync.ts b/test/remote_base/sync_trysync.ts new file mode 100644 index 00000000..8e2f0f04 --- /dev/null +++ b/test/remote_base/sync_trysync.ts @@ -0,0 +1,1226 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test sync + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import git from 'isomorphic-git'; +import fs from 'fs-extra'; +import expect from 'expect'; +import sinon from 'sinon'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { RemoteEngine, RemoteErr } from '../../src/remote/remote_engine'; +import { + ConnectionSettings, + RemoteOptions, + SyncResult, + SyncResultFastForwardMerge, + SyncResultMergeAndPush, + SyncResultPush, +} from '../../src/types'; + +import { + compareWorkingDirAndBlobs, + createClonedDatabases, + createDatabase, + destroyDBs, + getChangedFileDelete, + getChangedFileInsert, + getChangedFileUpdate, + getCommitInfo, + getWorkingDirDocs, + removeRemoteRepositories, + resetRemoteCommonRepository, +} from '../remote_utils'; +import { sleep, toSortedJSONString } from '../../src/utils'; +import { JSON_POSTFIX } from '../../src/const'; +import { Err } from '../../src/error'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pushWorker_module = require('../../src/remote/push_worker'); + +export const syncTrySyncBase = ( + connection: ConnectionSettings, + remoteURLBase: string, + reposPrefix: string, + localDir: string +) => () => { + let idCounter = 0; + const serialId = () => { + return `${reposPrefix}${idCounter++}`; + }; + + // Use commonId to reduce API calls to GitHub + const commonId = () => { + return `${reposPrefix}common`; + }; + + // Use sandbox to restore stub and spy in parallel mocha tests + let sandbox: sinon.SinonSandbox; + beforeEach(function () { + // To avoid secondary rate limit of GitHub + // await new Promise(resolve => setTimeout(resolve, 3000)); + + sandbox = sinon.createSandbox(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + before(async () => { + await removeRemoteRepositories(reposPrefix); + }); + + describe(': Sync#trySync()', () => { + /** + * before: + * dbA : + * after : + */ + it('returns SyncResultNop when no commit', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const syncResult1 = (await syncA.trySync()) as SyncResultPush; + + expect(syncResult1.action).toBe('nop'); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + describe('returns SyncResultPush', () => { + /** + * before: + * dbA : jsonA1 + * after : jsonA1 + */ + it('which includes one remote creation when a local db creates a document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const syncResult1 = (await syncA.trySync()) as SyncResultPush; + + expect(syncResult1.action).toBe('push'); + expect(syncResult1.commits!.remote.length).toBe(1); + expect(syncResult1.commits!.remote[0].oid).toBe(putResultA1.commit.oid); + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileInsert(jsonA1, putResultA1), + ]); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: jsonA1 + * dbA : -jsonA1 + * after : + */ + it('which includes one remote delete when a local db deletes a document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const deleteResultA1 = await dbA.delete(jsonA1); + const syncResult1 = (await syncA.trySync()) as SyncResultPush; + + expect(syncResult1.action).toBe('push'); + expect(syncResult1.commits!.remote.length).toBe(1); + expect(syncResult1.commits!.remote[0].oid).toBe(deleteResultA1.commit.oid); + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileDelete(jsonA1, deleteResultA1), + ]); + + expect(getWorkingDirDocs(dbA)).toEqual([]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * after : jsonA1 + */ + it('which includes one remote update when a local db a document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + const syncResult1 = (await syncA.trySync()) as SyncResultPush; + + expect(syncResult1.action).toBe('push'); + expect(syncResult1.commits!.remote.length).toBe(1); + expect(syncResult1.commits!.remote[0].oid).toBe(putResultA1dash.commit.oid); + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileUpdate(jsonA1, putResultA1, jsonA1dash, putResultA1dash), + ]); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + + await destroyDBs([dbA]); + }); + }); + + describe('returns SyncResultFastForwardMerge', () => { + /** + * before: + * dbA : jsonA1 + * dbB : + * after : jsonA1 + */ + it('which includes one local creation when a remote db creates a document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { connection } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + + await syncA.tryPush(); + + // B syncs + const syncResult1 = (await syncB.trySync()) as SyncResultFastForwardMerge; + expect(syncResult1.action).toBe('fast-forward merge'); + expect(syncResult1.commits!.local.length).toBe(1); + expect(syncResult1.commits!.local[0].oid).toBe(putResult1.commit.oid); + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA1, putResult1), + ]); + + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: + * dbA : jsonA1 jsonA2 + * dbB : + * after : jsonA1 jsonA2 + */ + it('which includes two local creations when a remote db creates two documents', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResult1 = await dbA.put(jsonA1); + const putResult2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B syncs + const syncResult1 = (await syncB.trySync()) as SyncResultFastForwardMerge; + expect(syncResult1.action).toBe('fast-forward merge'); + expect(syncResult1.commits!.local.length).toBe(2); + expect(syncResult1.commits!.local[0].oid).toBe(putResult1.commit.oid); + expect(syncResult1.commits!.local[1].oid).toBe(putResult2.commit.oid); + expect(syncResult1.changes.local.length).toBe(2); + expect(syncResult1.changes.local).toEqual( + expect.arrayContaining([ + getChangedFileInsert(jsonA1, putResult1), + getChangedFileInsert(jsonA2, putResult2), + ]) + ); + + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonA2]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + // Check HEAD + const headCommitA = await git.resolveRef({ + fs, + dir: dbA.workingDir, + ref: 'HEAD', + }); + expect(headCommitA).toBe(putResult2.commit.oid); + + const headCommitB = await git.resolveRef({ + fs, + dir: dbB.workingDir, + ref: 'HEAD', + }); + expect(headCommitB).toBe(putResult2.commit.oid); + + // Check defaultBranch + const mainBranchA = await git.resolveRef({ + fs, + dir: dbA.workingDir, + ref: 'refs/heads/main', + }); + expect(mainBranchA).toBe(putResult2.commit.oid); + + const mainBranchB = await git.resolveRef({ + fs, + dir: dbB.workingDir, + ref: 'refs/heads/main', + }); + expect(mainBranchB).toBe(putResult2.commit.oid); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe('returns SyncResultMergeAndPush', () => { + /** + * before: + * dbA : jsonA1 + * dbB : jsonB2 + * after : jsonA1 jsonB2 + */ + it('which includes local and remote creations when a remote db creates a document and a local db creates another document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { connection } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B syncs + const jsonB2 = { _id: '2', name: 'fromB' }; + const putResultB2 = await dbB.put(jsonB2); + + // Sync dbB + const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; + expect(syncResult1.action).toBe('merge and push'); + + expect(syncResult1.commits!.local.length).toBe(2); // put commit and merge commit + expect(syncResult1.commits!.remote.length).toBe(2); // put commit and merge commit + expect(syncResult1.commits!.local[0].oid).toBe(putResultA1.commit.oid); + expect(syncResult1.commits!.local[1].message).toBe('merge'); + expect(syncResult1.commits!.remote[0].oid).toBe(putResultB2.commit.oid); + expect(syncResult1.commits!.remote[1].message).toBe('merge'); + + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA1, putResultA1), + ]); + + expect(syncResult1.changes.remote).toEqual([ + getChangedFileInsert(jsonB2, putResultB2), + ]); + + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonB2]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: + * dbA : jsonA1 jsonA2 + * dbB : jsonB3 jsonB4 + * after : jsonA1 jsonA2 jsonB3 jsonB4 + */ + it('which includes two local creations and two remote creations when a remote db creates two documents and a local db creates two different documents', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { connection } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B syncs + const jsonB3 = { _id: '3', name: 'fromB' }; + const putResultB3 = await dbB.put(jsonB3); + const jsonB4 = { _id: '4', name: 'fromB' }; + const putResultB4 = await dbB.put(jsonB4); + + const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; + expect(syncResult1.action).toBe('merge and push'); + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([putResultA1, putResultA2, 'merge']), + remote: getCommitInfo([putResultB3, putResultB4, 'merge']), + }); + + expect(syncResult1.changes.local.length).toBe(2); + expect(syncResult1.changes.local).toEqual( + expect.arrayContaining([ + getChangedFileInsert(jsonA1, putResultA1), + getChangedFileInsert(jsonA2, putResultA2), + ]) + ); + + expect(syncResult1.changes.remote.length).toBe(2); + expect(syncResult1.changes.remote).toEqual( + expect.arrayContaining([ + getChangedFileInsert(jsonB3, putResultB3), + getChangedFileInsert(jsonB4, putResultB4), + ]) + ); + + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1, jsonA2, jsonB3, jsonB4]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1, jsonA2, jsonB3, jsonB4]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: + * dbA : jsonA1 + * dbB : jsonA1 + * after : jsonA1 + */ + it('which does not include changes after a remote db creates a document and a local db creates exactly the same document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, dbB, syncA, syncB] = await createClonedDatabases( + remoteURLBase, + localDir, + serialId, + commonId, + { connection } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // B puts the same file with exactly the same contents + const putResultB1 = await dbB.put(jsonA1); + + const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; + expect(syncResult1.action).toBe('merge and push'); + + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([putResultA1, 'merge']), + remote: getCommitInfo([putResultB1, 'merge']), + }); + + expect(syncResult1.changes.local.length).toBe(0); + expect(syncResult1.changes.remote.length).toBe(0); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : +jsonA1 + * dbB : +jsonA1 + * after : jsonA1 + */ + it('which does not include changes after a remote db updates a document and a local db updates exactly the same update', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // Clone + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A updates and pushes + const jsonA1dash = { _id: '1', name: 'updated' }; + const putResultA1dash = await dbA.put(jsonA1dash); + await syncA.tryPush(); + + // B updates the same file with exactly the same contents + const putResultB1dash = await dbB.put(jsonA1dash); + + const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; + expect(syncResult1.action).toBe('merge and push'); + + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([putResultA1dash, 'merge']), + remote: getCommitInfo([putResultB1dash, 'merge']), + }); + + expect(syncResult1.changes.local.length).toBe(0); + expect(syncResult1.changes.remote.length).toBe(0); + + expect(getWorkingDirDocs(dbA)).toEqual([jsonA1dash]); + expect(getWorkingDirDocs(dbB)).toEqual([jsonA1dash]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : jsonA2 + * dbB : -jsonA1 + * after : jsonA2 + */ + it('which include a local create and a remote delete when a remote db creates a document and a local db deletes another document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A puts and pushes + const jsonA2 = { _id: '2', name: 'fromA' }; + const putResultA2 = await dbA.put(jsonA2); + await syncA.tryPush(); + + // B deletes and syncs + const deleteResultB1 = await dbB.delete(jsonA1); + + const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; + expect(syncResult1.action).toBe('merge and push'); + + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([putResultA2, 'merge']), + remote: getCommitInfo([deleteResultB1, 'merge']), + }); + + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileInsert(jsonA2, putResultA2), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileDelete(jsonA1, deleteResultB1), + ]); + + expect(getWorkingDirDocs(dbB)).toEqual([jsonA2]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonA2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : -jsonA1 + * dbB : jsonB2 + * after : jsonB2 + */ + it('which include a remote create and a local delete when a remote db deletes a document and a local db creates another document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A deletes and pushes + const deleteResultA1 = await dbA.delete(jsonA1); + await syncA.tryPush(); + + // B put another file and syncs + const jsonB2 = { _id: '2', name: 'fromB' }; + const putResultB2 = await dbB.put(jsonB2); + + const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; + expect(syncResult1.action).toBe('merge and push'); + + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([deleteResultA1, 'merge']), + remote: getCommitInfo([putResultB2, 'merge']), + }); + + expect(syncResult1.changes.local.length).toBe(1); + expect(syncResult1.changes.local).toEqual([ + getChangedFileDelete(jsonA1, deleteResultA1), + ]); + + expect(syncResult1.changes.remote.length).toBe(1); + expect(syncResult1.changes.remote).toEqual([ + getChangedFileInsert(jsonB2, putResultB2), + ]); + + expect(getWorkingDirDocs(dbB)).toEqual([jsonB2]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([jsonB2]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + + /** + * before: jsonA1 + * dbA : -jsonA1 + * dbB : -jsonA1 + * after : + */ + it('which does not include changes when a remote db deletes a document and a local db deletes the same document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + // A puts and pushes + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + await syncA.tryPush(); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + // A deletes and pushes + const deleteResultA1 = await dbA.delete(jsonA1); + await syncA.tryPush(); + + // B deletes the same file and syncs + const deleteResultB1 = await dbB.delete(jsonA1); + + const syncResult1 = (await syncB.trySync()) as SyncResultMergeAndPush; + expect(syncResult1.action).toBe('merge and push'); + + expect(syncResult1.commits).toMatchObject({ + local: getCommitInfo([deleteResultA1, 'merge']), + remote: getCommitInfo([deleteResultB1, 'merge']), + }); + + expect(syncResult1.changes.local.length).toBe(0); // Must no be 1 but 0, because diff is empty. + expect(syncResult1.changes.remote.length).toBe(0); // Must no be 1 but 0, because diff is empty. + + expect(getWorkingDirDocs(dbB)).toEqual([]); + + // Sync dbA + const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; + expect(getWorkingDirDocs(dbA)).toEqual([]); + + await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); + await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); + + await destroyDBs([dbA, dbB]); + }); + }); + + describe('returns SyncResolveConflictAndPush', () => { + it('when two databases put the same _id document', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const remoteURL = remoteURLBase + commonId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + const syncB = await dbB.sync(options); + + const jsonA1 = { _id: '1', name: 'fromA' }; + const putResultA1 = await dbA.put(jsonA1); + await syncA.tryPush(); + + // The same id + const jsonB1 = { _id: '1', name: 'fromB' }; + const putResultB1 = await dbB.put(jsonB1); + + await expect(syncB.trySync()).resolves.toMatchObject({ + action: 'resolve conflicts and push', + changes: { + local: [], + remote: [getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1)], + }, + conflicts: [ + { + fatDoc: { + _id: jsonB1._id, + name: jsonB1._id + JSON_POSTFIX, + fileOid: putResultB1.fileOid, + type: 'json', + doc: jsonB1, + }, + operation: 'insert-merge', + strategy: 'ours-diff', + }, + ], + }); + + await destroyDBs([dbA, dbB]); + }); + }); + + it('skips consecutive sync tasks', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + const results: SyncResult[] = []; + + for (let i = 0; i < 3; i++) { + // eslint-disable-next-line promise/catch-or-return + syncA.trySync().then(result => results.push(result)); + } + await sleep(5000); + + // results will be include 9 cancels + let cancelCount = 0; + results.forEach(res => { + if (res.action === 'canceled') cancelCount++; + }); + // Check results + expect(cancelCount).toBeGreaterThanOrEqual(1); + + // Check statistics + expect(dbA.taskQueue.currentStatistics().cancel).toBeGreaterThanOrEqual(1); + + // Only one trySync() will be executed + expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThanOrEqual(1); + + await destroyDBs([dbA]); + }); + + it('skips consecutive sync tasks after crud tasks', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const jsonA1 = { _id: '1', name: 'fromA' }; + for (let i = 0; i < 10; i++) { + dbA.put(jsonA1); + } + const results: SyncResult[] = []; + for (let i = 0; i < 3; i++) { + // eslint-disable-next-line promise/catch-or-return + syncA.trySync().then(result => results.push(result)); + } + await sleep(10000); + + // results will be include cancels + let cancelCount = 0; + results.forEach(res => { + if (res.action === 'canceled') cancelCount++; + }); + // Check results + expect(cancelCount).toBeGreaterThanOrEqual(1); + + // Check statistics + expect(dbA.taskQueue.currentStatistics().cancel).toBeGreaterThanOrEqual(1); + + // Only one trySync() will be executed + expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThanOrEqual(1); + + await destroyDBs([dbA]); + }); + + it('skips consecutive put tasks mixed with sync tasks', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + + const putter: Promise[] = []; + const validResult: (boolean | Record)[] = []; + for (let i = 1; i < 10; i++) { + putter.push( + dbA + .put({ _id: 'a', name: `${i}` }, { taskId: `${i}`, debounceTime: 3000 }) + .catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + } + + const syncResults: SyncResult[] = []; + for (let i = 0; i < 3; i++) { + // eslint-disable-next-line promise/catch-or-return + syncA.trySync().then(result => syncResults.push(result)); + } + + for (let i = 10; i < 20; i++) { + putter.push( + dbA + .put({ _id: 'a', name: `${i}` }, { taskId: `${i}`, debounceTime: 3000 }) + .catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + } + putter.push( + dbA + .put({ _id: 'a', name: '20' }, { taskId: '20', debounceTime: 3000 }) + .catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push({ _id: 'a' }); + const results = await Promise.all(putter); + + await sleep(10000); + + // Check skipped put() + expect(results).toMatchObject(validResult); + const json = await dbA.get('a'); + expect(json!.name).toEqual('20'); + + // Check sync + let cancelCount = 0; + syncResults.forEach(res => { + if (res.action === 'canceled') cancelCount++; + }); + expect(cancelCount).toBeGreaterThanOrEqual(1); + expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThanOrEqual(1); + + dbA.taskQueue.stop(); + + await destroyDBs([dbA]); + }); + + it('syncs files under .gitddb', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + } + ); + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir, + }); + // Clone dbA + await dbB.open(); + const syncB = await dbB.sync(syncA.options); + + const info = { + dbId: 'foo', + creator: 'bar', + version: 'baz', + }; + const putResult = await dbA.putFatDoc('.gitddb/info.json', toSortedJSONString(info)); + + await syncA.tryPush(); + + await syncB.trySync(); + + const fatDoc = { + _id: '.gitddb/info', + name: '.gitddb/info.json', + fileOid: putResult.fileOid, + type: 'json', + doc: info, + }; + const mergedFatDoc = await dbB.getFatDoc('.gitddb/info.json'); + + expect(mergedFatDoc).toEqual(fatDoc); + + await destroyDBs([dbA, dbB]); + }); + + it('pauses live sync after error', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const [dbA, syncA] = await createDatabase( + remoteURLBase, + localDir, + serialId, + commonId, + { + connection, + live: true, + interval: 3000, + } + ); + expect(syncA.options.live).toBeTruthy(); + + dbA.put({ name: 'fromA' }); + + let error: Error | undefined; + syncA.on('error', (err: Error) => { + error = err; + }); + const stubPush = sandbox.stub(RemoteEngine[syncA.engine], 'push'); + stubPush.onFirstCall().throwsException(new RemoteErr.NetworkError('foo')); + + for (let i = 0; i < 10; i++) { + // eslint-disable-next-line no-await-in-loop + await sleep(1000); + if (error instanceof Error) { + break; + } + } + + expect(error).toBeInstanceOf(RemoteErr.NetworkError); + // expect(syncA.options.live).toBeFalsy(); + + await destroyDBs([dbA]); + }); + + /** + * Retry sync + */ + describe('Retry trySync', () => { + it('does not retry when retry option is 0 after UnfetchedCommitExistsError', async () => { + // Cannot use common repository when syncDirection is 'push' + // await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + + const options: RemoteOptions = { + remoteUrl: remoteURL, + syncDirection: 'push', + retryInterval: 0, + retry: 0, + connection, + }; + + const sync = await dbA.sync(options); + await dbA.put({ name: 'fromA' }); + + const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); + stubPush.rejects(new RemoteErr.UnfetchedCommitExistsError('')); + + await expect(sync.trySync()).rejects.toThrowError( + RemoteErr.UnfetchedCommitExistsError + ); + + expect(stubPush.callCount).toBe(1); + + await destroyDBs([dbA]); + }); + + it('retries every retry interval and fails after UnfetchedCommitExistsError', async () => { + // Cannot use common repository when syncDirection is 'push' + // await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + + const interval = 100000; + const retryInterval = 5000; + + const options: RemoteOptions = { + remoteUrl: remoteURL, + syncDirection: 'push', + interval, + retryInterval, + retry: 2, + connection, + }; + + const sync = await dbA.sync(options); + await dbA.put({ name: 'fromA' }); + + const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); + stubPush.rejects(new RemoteErr.UnfetchedCommitExistsError('')); + + await expect(sync.trySync()).rejects.toThrowError( + RemoteErr.UnfetchedCommitExistsError + ); + + expect(stubPush.callCount).toBe(3); + + await destroyDBs([dbA]); + }); + + it('retries every retry interval and succeeds after UnfetchedCommitExistsError', async () => { + // Cannot use common repository when syncDirection is 'push' + // await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const remoteURL = remoteURLBase + serialId(); + const dbNameA = serialId(); + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + await dbA.open(); + + const interval = 100000; + const retryInterval = 5000; + + const options: RemoteOptions = { + remoteUrl: remoteURL, + syncDirection: 'push', + interval, + retryInterval, + retry: 2, + connection, + }; + + const sync = await dbA.sync(options); + await dbA.put({ name: 'fromA' }); + + const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); + stubPush + .onFirstCall() + .throwsException(new RemoteErr.UnfetchedCommitExistsError('')); + stubPush + .onSecondCall() + .throwsException(new RemoteErr.UnfetchedCommitExistsError('')); + stubPush + .onThirdCall() + .returns(Promise.resolve({ action: 'push', changes: { remote: [] } })); + + await expect(sync.trySync()).resolves.not.toThrowError(); + + expect(stubPush.callCount).toBe(3); + + await destroyDBs([dbA]); + }); + + it('Race condition of two trySync() calls does not throw UnfetchedCommitExistsError.', async () => { + await resetRemoteCommonRepository(remoteURLBase, localDir, serialId, commonId); + const remoteURL = remoteURLBase + commonId(); + const dbNameA = serialId(); + + const dbA: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameA, + localDir: localDir, + }); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection, + }; + await dbA.open(); + const syncA = await dbA.sync(options); + const jsonA1 = { _id: '1', name: 'fromA' }; + await dbA.put(jsonA1); + + const dbNameB = serialId(); + const dbB: GitDocumentDB = new GitDocumentDB({ + dbName: dbNameB, + localDir: localDir, + }); + await dbB.open(); + const syncB = await dbB.sync(options); + const jsonB1 = { _id: '1', name: 'fromB' }; + await dbB.put(jsonB1); + + // It will retry due to RemoteErr.UnfetchedCommitExistsError + await expect( + Promise.all([syncA.trySync(), syncB.trySync()]) + ).resolves.not.toThrowError(); + + await destroyDBs([dbA, dbB]); + }); + }); + }); +}; diff --git a/test/remote_isomorphic_git/3way_merge.test.ts b/test/remote_isomorphic_git/3way_merge.test.ts new file mode 100644 index 00000000..698c0c9b --- /dev/null +++ b/test/remote_isomorphic_git/3way_merge.test.ts @@ -0,0 +1,59 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test tryPush + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncThreeWayMergeBase } from '../remote_base/3way_merge'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_3way_merge_isomorphic_git__'; +const localDir = `./test/database_3way_merge_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe( + 'isomorphic-git', + syncThreeWayMergeBase(connection, remoteURLBase, reposPrefix, localDir) +); diff --git a/test/remote_isomorphic_git/3way_merge_ot.test.ts b/test/remote_isomorphic_git/3way_merge_ot.test.ts new file mode 100644 index 00000000..75340ee7 --- /dev/null +++ b/test/remote_isomorphic_git/3way_merge_ot.test.ts @@ -0,0 +1,59 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test trySync + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { threeWayMergeOtBase } from '../remote_base/3way_merge_ot'; + +const reposPrefix = 'test_3way_merge_ot_isomorphic_git__'; +const localDir = `./test/database_3way_merge_ot_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe( + 'isomorphic-git', + threeWayMergeOtBase(connection, remoteURLBase, reposPrefix, localDir) +); diff --git a/test/remote_isomorphic_git/combine.test.ts b/test/remote_isomorphic_git/combine.test.ts new file mode 100644 index 00000000..6c520f78 --- /dev/null +++ b/test/remote_isomorphic_git/combine.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test combine databases + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncCombineBase } from '../remote_base/combine'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_combine_isomorphic_git__'; +const localDir = `./test/database_combine_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe('isomorphic-git', syncCombineBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test/remote_isomorphic_git/network_git_documentdb.test.ts b/test/remote_isomorphic_git/network_git_documentdb.test.ts new file mode 100644 index 00000000..26c8d164 --- /dev/null +++ b/test/remote_isomorphic_git/network_git_documentdb.test.ts @@ -0,0 +1,59 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for GitDocumentDB class + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { networkGitDocumentDBBase } from '../remote_base/network_git_documentdb'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_network_git_documentdb_isomorphic_git__'; +const localDir = `./test/database_network_git_documentdb_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe( + 'isomorphic-git', + networkGitDocumentDBBase(connection, remoteURLBase, reposPrefix, localDir) +); diff --git a/test/remote_isomorphic_git/network_history.test.ts b/test/remote_isomorphic_git/network_history.test.ts new file mode 100644 index 00000000..dbf3e244 --- /dev/null +++ b/test/remote_isomorphic_git/network_history.test.ts @@ -0,0 +1,59 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for history + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { networkHistoryBase } from '../remote_base/network_history'; + +const reposPrefix = 'test_network_history_isomorphic_git__'; +const localDir = `./test/database_network_history_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe( + 'isomorphic-git', + networkHistoryBase(connection, remoteURLBase, reposPrefix, localDir) +); diff --git a/test/remote_isomorphic_git/network_task_queue.test.ts b/test/remote_isomorphic_git/network_task_queue.test.ts new file mode 100644 index 00000000..333c985e --- /dev/null +++ b/test/remote_isomorphic_git/network_task_queue.test.ts @@ -0,0 +1,59 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for TaskQueue + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { networkTaskQueueBase } from '../remote_base/network_task_queue'; + +const reposPrefix = 'test_network_task_queue_isomorphic_git__'; +const localDir = `./test/database_network_task_queue_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe( + 'isomorphic-git', + networkTaskQueueBase(connection, remoteURLBase, reposPrefix, localDir) +); diff --git a/test/remote_isomorphic_git/on_sync_event.test.ts b/test/remote_isomorphic_git/on_sync_event.test.ts new file mode 100644 index 00000000..7c0d7434 --- /dev/null +++ b/test/remote_isomorphic_git/on_sync_event.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test trySync + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { onSyncEventBase } from '../remote_base/on_sync_event'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_on_sync_event_isomorphic_git__'; +const localDir = `./test/database_on_sync_event_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe('isomorphic-git', onSyncEventBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test/remote_isomorphic_git/sync.test.ts b/test/remote_isomorphic_git/sync.test.ts new file mode 100644 index 00000000..71f15233 --- /dev/null +++ b/test/remote_isomorphic_git/sync.test.ts @@ -0,0 +1,52 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { syncBase } from '../remote_base/sync'; + +const reposPrefix = 'test_sync_constructor_isomorphic_git__'; +const localDir = `./test/database_sync_constructor_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'isomorphic-git', +}; + +maybe('isomorphic-git', syncBase(connection, remoteURLBase, reposPrefix, localDir, token)); diff --git a/test/remote_isomorphic_git/sync_clone.test.ts b/test/remote_isomorphic_git/sync_clone.test.ts new file mode 100644 index 00000000..8c38024b --- /dev/null +++ b/test/remote_isomorphic_git/sync_clone.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test tryPush + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncCloneBase } from '../remote_base/sync_clone'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_sync_clone_isomorphic_git___'; +const localDir = `./test/database_sync_clone_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe('isomorphic-git', syncCloneBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test/remote_isomorphic_git/sync_events.test.ts b/test/remote_isomorphic_git/sync_events.test.ts new file mode 100644 index 00000000..57b4b8b2 --- /dev/null +++ b/test/remote_isomorphic_git/sync_events.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test Sync Events + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncEventsBase } from '../remote_base/sync_events'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_sync_events_isomorphic_git___'; +const localDir = `./test/database_sync_events_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe('isomorphic-git', syncEventsBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test/remote_isomorphic_git/sync_live.test.ts b/test/remote_isomorphic_git/sync_live.test.ts new file mode 100644 index 00000000..b274864f --- /dev/null +++ b/test/remote_isomorphic_git/sync_live.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test Sync live + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncLiveBase } from '../remote_base/sync_live'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_sync_live_isomorphic_git___'; +const localDir = `./test/database_sync_live_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe('isomorphic-git', syncLiveBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test/remote_isomorphic_git/sync_trypush.test.ts b/test/remote_isomorphic_git/sync_trypush.test.ts new file mode 100644 index 00000000..c6465286 --- /dev/null +++ b/test/remote_isomorphic_git/sync_trypush.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test tryPush + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncTryPushBase } from '../remote_base/sync_trypush'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_sync_trypush_isomorphic-git___'; +const localDir = `./test/database_sync_trypush_isomorphic-git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe('isomorphic-git', syncTryPushBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test/remote_isomorphic_git/sync_trysync.test.ts b/test/remote_isomorphic_git/sync_trysync.test.ts new file mode 100644 index 00000000..45090ce2 --- /dev/null +++ b/test/remote_isomorphic_git/sync_trysync.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test trySync + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncTrySyncBase } from '../remote_base/sync_trysync'; +import { ConnectionSettingsGitHub } from '../../src/types'; + +const reposPrefix = 'test_sync_trysync_isomorphic_git___'; +const localDir = `./test/database_sync_trysync_isomorphic_git`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + // fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, +}; + +maybe('isomorphic-git', syncTrySyncBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test/remote/json_diff.test.ts b/test/remote_offline/json_diff.test.ts similarity index 97% rename from test/remote/json_diff.test.ts rename to test/remote_offline/json_diff.test.ts index 2ac387b1..8ed78528 100644 --- a/test/remote/json_diff.test.ts +++ b/test/remote_offline/json_diff.test.ts @@ -1,4 +1,11 @@ /* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ import expect from 'expect'; import { JsonDiff } from '../../src/remote/json_diff'; @@ -9,6 +16,10 @@ const textOTDiff = new JsonDiff({ }); describe(' diff', () => { + it('Equal', () => { + expect(textOTDiff.diff({}, {})).toBeUndefined(); + }); + describe('primitives', () => { it('adding values', () => { const oldDoc = { @@ -384,7 +395,7 @@ describe(' diff', () => { it('of object by objectHash', () => { const myDiff = new JsonDiff({ - idOfSubtree: ['place'], + keyInArrayedObject: ['place'], }); const oldDoc = { diff --git a/test/remote_offline/json_patch_ot.test.ts b/test/remote_offline/json_patch_ot.test.ts new file mode 100644 index 00000000..9aaf90c2 --- /dev/null +++ b/test/remote_offline/json_patch_ot.test.ts @@ -0,0 +1,2697 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { editOp, type } from 'ot-json1'; +import expect from 'expect'; +import { JsonDiff } from '../../src/remote/json_diff'; +import { JsonPatchOT } from '../../src/remote/json_patch_ot'; + +const primitiveDiff = new JsonDiff(); + +const textOTDiff = new JsonDiff({ + plainTextProperties: { text: true }, +}); + +const jPatch = new JsonPatchOT(); + +const jPatchUniqueArray = new JsonPatchOT({ + keyOfUniqueArray: ['unique'], +}); + +describe(' OT', () => { + describe('apply:', () => { + it('apply op', () => { + const oldDoc = { + _id: 'oldId', + }; + const op = ['_id', { r: true, i: 'newId' }]; + + expect(jPatch.apply(oldDoc, op)).toStrictEqual({ + _id: 'newId', + }); + }); + + it('apply empty op', () => { + const oldDoc = { + _id: 'oldId', + }; + // Do not be undefined. Use null. + expect(jPatch.apply(oldDoc, null)).toStrictEqual({ + _id: 'oldId', + }); + }); + + it('apply complex op', () => { + const oldDoc = { + _id: 'old', + collapsedList: [163, 339, 451, 559, 604], + condition: {}, + geometry: { height: 686, width: 410, x: 390, y: 4, z: 8931 }, + label: { + height: 64, + status: 'closed', + text: 'old', + width: 400, + x: 390, + y: 4, + zoom: 1, + }, + }; + + const op = [ + [ + 'collapsedList', + [0, { r: true }], + [1, { r: true }], + [2, { r: true }], + [3, { r: true }], + [4, { r: true }], + ], + [ + 'geometry', + ['height', { r: true, i: 980 }], + ['width', { r: true, i: 650 }], + ['z', { r: true, i: 8937 }], + ], + [ + 'label', + 'text', + { + r: true, + i: 'updated', + }, + ], + ]; + + const newDoc = { + _id: 'old', + collapsedList: [], + condition: {}, + geometry: { height: 980, width: 650, x: 390, y: 4, z: 8937 }, + label: { + height: 64, + status: 'closed', + text: 'updated', + width: 400, + x: 390, + y: 4, + zoom: 1, + }, + }; + expect(jPatch.apply(oldDoc, op)).toStrictEqual(newDoc); + }); + + it('applies patch (create)', () => { + const oldDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + }; + const newDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + age2: 'Heijo-kyo', + year2: 710, + current2: false, + }; + /* + const diff = { + age2: ['Heijo-kyo'], + year2: [710], + current2: [false], + }; + expect(primitiveDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + */ + // keys must be sorted by descendant order + const patch = [ + ['age2', { i: 'Heijo-kyo' }], + ['current2', { i: false }], + ['year2', { i: 710 }], + ]; + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + }); + + describe('patch:', () => { + it('patches from undefined diff', () => { + const oldDoc = { + _id: 'nara', + }; + const newDoc = { + _id: 'nara', + }; + // primitiveDiff.diff(oldDoc, newDoc) will return undefined. + expect(primitiveDiff.diff(oldDoc, newDoc)).toBeUndefined(); + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + }); + + describe('for array:', () => { + it('new property', () => { + const oldDoc = { + _id: 'nara', + }; + const newDoc = { + _id: 'nara', + temple: ['Toshodaiji', 'Todaiji', 'Yakushiji'], + }; + + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('delete property', () => { + const oldDoc = { + _id: 'nara', + temple: ['Toshodaiji', 'Todaiji', 'Yakushiji'], + }; + const newDoc = { + _id: 'nara', + }; + + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + describe('insert:', () => { + it('insert to empty array', () => { + const oldDoc = { + _id: 'nara', + temple: [], + }; + const newDoc = { + _id: 'nara', + temple: ['Toshodaiji'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('insert at first', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['3', '1', '2'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('insert at middle', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['1', '3', '2'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('insert at last', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['1', '2', '3'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('insert two members', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['1', '3', '4', '2'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('insert two members at a distance', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['1', '3', '2', '4'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + }); + + describe('move:', () => { + it('move from the first to the last(1)', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['2', '3', '1'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + // console.log(diff); + // { number: { _t: 'a', _0: [ '', 2, 3 ] } } + // The first member is always ''. + // The second member 0 represents destinationIndex + // The last member 3 is the magical number that indicates "array move" + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('move from the first to the last(2)', () => { + const oldDoc = { + number: ['1', '2', '3', '4'], + }; + const newDoc = { + number: ['2', '3', '4', '1'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('move from the last to the first(1)', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['3', '1', '2'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + // console.log(diff); + // { number: { _t: 'a', _2: [ '', 0, 3 ] } } + // The first member is always ''. + // The second member 0 represents destinationIndex + // The last member 3 is the magical number that indicates "array move" + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('move from the last to the first(2)', () => { + const oldDoc = { + number: ['1', '2', '3', '4'], + }; + const newDoc = { + number: ['4', '1', '2', '3'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('replace the last with the first(1)', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['3', '2', '1'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('replace the last with the first(2)', () => { + const oldDoc = { + number: ['1', '2', '3', '4'], + }; + const newDoc = { + number: ['4', '2', '3', '1'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('reverse', () => { + const oldDoc = { + number: ['1', '2', '3', '4'], + }; + const newDoc = { + number: ['4', '3', '2', '1'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('shuffle', () => { + const oldDoc = { + number: ['1', '2', '3', '4', '5'], + }; + const newDoc = { + number: ['4', '3', '2', '5', '1'], + }; + + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + }); + + describe('delete:', () => { + it('delete one', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['1'], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('delete middle one', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['1', '3'], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('delete the last two', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['1'], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('delete the first two', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['3'], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('delete two at a distance', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['2'], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('clear array', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: [], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + }); + + describe('delete and insert:', () => { + it('delete one, then insert new one at the first position', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['3', '2'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('delete the first, then insert the last', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['2', '3'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('delete one, then insert new one', () => { + const oldDoc = { + number: ['1'], + }; + const newDoc = { + number: ['2'], + }; + + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('delete two, then insert new one', () => { + const oldDoc = { + number: ['1', '2'], + }; + const newDoc = { + number: ['3'], + }; + + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + }); + + describe('delete and move:', () => { + it('delete the first, then move the third to the second', () => { + const oldDoc = { + _id: 'nara', + number: ['1', '2', '3', '4'], + }; + const newDoc = { + _id: 'nara', + number: ['2', '4', '3'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('delete the third, then move the first to the last', () => { + const oldDoc = { + _id: 'nara', + number: ['1', '2', '3', '4'], + }; + const newDoc = { + _id: 'nara', + number: ['2', '4', '1'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('delete the first, then move the last to the first', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['3', '2'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('delete the second, then move the last to the first', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['3', '1'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + }); + + describe('insert and move:', () => { + it('insert the first, then move the last to the second', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['4', '3', '2', '1'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('insert the first, then move the last to the first', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['3', '4', '1', '2'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + }); + + describe('composite:', () => { + it('insert after the second, insert after the third, remove the last, then move the first to the last', () => { + const oldDoc = { + number: ['1', '2', '3'], + }; + const newDoc = { + number: ['2', '4', '5', '1'], + }; + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + }); + + it('nesting arrays', () => { + const oldDoc = { + cherry: [ + ['NaraPark', 'double cherry blossoms'], + ['MtYoshino', 'cherry blossoms'], + ], + }; + const newDoc = { + cherry: [ + ['NaraPark', 'double cherry blossoms'], + ['MtYoshino', 'awesome cherry blossoms'], + ], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('of objects', () => { + const oldDoc = { + _id: 'nara', + site: [ + { place: 'NaraPark', flower: ['cherry blossoms'] }, + { place: 'MtYoshino', flower: ['cherry blossoms'] }, + ], + }; + + const newDoc = { + _id: 'nara', + site: [ + { place: 'MtYoshino', flower: ['cherry blossoms'] }, + { place: 'NaraPark', flower: ['double cherry blossoms', 'Japanese apricot'] }, + ], + }; + const diff = primitiveDiff.diff(oldDoc, newDoc)!; + console.log(JSON.stringify(diff)); + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('of objects by objectHash', () => { + const myDiff = new JsonDiff({ + keyInArrayedObject: ['place'], + }); + + const oldDoc = { + _id: 'nara', + site: [ + { place: 'NaraPark', flower: ['cherry blossoms'] }, + { place: 'MtYoshino', flower: ['cherry blossoms'] }, + ], + }; + + const newDoc = { + _id: 'nara', + site: [ + { place: 'MtYoshino', flower: ['cherry blossoms'] }, + { place: 'NaraPark', flower: ['double cherry blossoms', 'Japanese apricot'] }, + ], + }; + const diff = myDiff.diff(oldDoc, newDoc)!; + console.log(JSON.stringify(diff)); + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + describe('merge:', () => { + it('merges insert and insert', () => { + const base = { + number: ['1', '2', '3'], + }; + + // move + const ours = { + number: ['1', '2', '4', '3'], + }; + + // replace + const theirs = { + number: ['1', '2', '3', '5'], + }; + + const merged = { + number: ['1', '2', '4', '3', '5'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges insert and insert (2)', () => { + const base = { + number: ['1', '2', '3'], + }; + + // move + const ours = { + number: ['1', '2', '4', '3'], + }; + + // replace + const theirs = { + number: ['1', '2', '5', '3'], + }; + + const merged = { + number: ['1', '2', '4', '5', '3'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges remove and remove', () => { + const base = { + number: ['1', '2', '3'], + }; + + // move + const ours = { + number: ['1', '2'], + }; + + // replace + const theirs = { + number: ['1', '3'], + }; + + const merged = { + number: ['1'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('replacing take precedence over moving', () => { + const base = { + number: ['1', '2', '3'], + }; + + // move + const ours = { + number: ['3', '1', '2'], + }; + + // replace + const theirs = { + number: ['1', '2', '4'], + }; + + /** + * Result is not ['4', '1', '2' ], + * Replacing take precedence over moving + */ + const merged = { + number: ['1', '2', '4'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('replacing take precedence over moving (reverse)', () => { + const base = { + number: ['1', '2', '3'], + }; + + // replace + const ours = { + number: ['1', '2', '4'], + }; + + // move + const theirs = { + number: ['3', '1', '2'], + }; + + /** + * Result is not ['4', '1', '2' ], + * Replacing take precedence over moving + */ + const merged = { + number: ['1', '2', '4'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('removing take precedence over moving', () => { + const base = { + number: ['1', '2', '3'], + }; + + // remove + const ours = { + number: ['1', '2'], + }; + + // move + const theirs = { + number: ['3', '1', '2'], + }; + + // Removing take precedence over moving + const merged = { + number: ['1', '2'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('removing take precedence over moving (reverse)', () => { + const base = { + number: ['1', '2', '3'], + }; + + // move + const ours = { + number: ['3', '1', '2'], + }; + + // remove + const theirs = { + number: ['1', '2'], + }; + + // Removing take precedence over moving + const merged = { + number: ['1', '2'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges remove and replace', () => { + const base = { + number: ['1', '2', '3'], + }; + + const ours = { + number: ['1', '2'], + }; + + const theirs = { + number: ['1', '2', '4'], + }; + + const merged = { + number: ['1', '2', '4'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges insert and remove', () => { + const base = { + number: ['1', '2', '3'], + }; + + const ours = { + number: ['1', '2'], + }; + + const theirs = { + number: ['4', '1', '2', '3'], + }; + + const merged = { + number: ['4', '1', '2'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges move and move the same', () => { + /** + * See https://github.com/ottypes/json1#limitations. + * > We're missing a conflict for situations + * > when two operations both move the same object to different locations. + * > Currently the left operation will silently 'win' + * > and the other operation's move will be discarded. + * > But this behaviour should be user configurable + */ + const base = { + number: ['1', '2', '3', '4', '5'], + }; + + const ours = { + number: ['5', '2', '3', '4', '1'], + }; + + // Move the same to another position + const theirs = { + number: ['1', '2', '3', '5', '4'], + }; + + // Ours wins silently. + const merged = { + number: ['5', '2', '3', '4', '1'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges move all and move all', () => { + const base = { + number: ['1', '2', '3', '4', '5'], + }; + + const ours = { + number: ['5', '3', '2', '4', '1'], + }; + + const theirs = { + number: ['3', '4', '1', '5', '2'], + }; + + /* + * TODO: + * The results are not predictable. + * JSON1 can not merge moves well. + * See https://github.com/ottypes/json1#limitations. + * > We're missing a conflict for situations + * > when two operations both move the same object to different locations. + * > Currently the left operation will silently 'win' + * > and the other operation's move will be discarded. + * > But this behaviour should be user configurable + */ + const merged = { + number: ['5', '3', '2', '4', '1'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges move all and move all (2)', () => { + const base = { + number: ['1', '2', '3', '4', '5'], + }; + + const ours = { + number: ['3', '4', '1', '5', '2'], + }; + + const theirs = { + number: ['5', '3', '2', '4', '1'], + }; + + /* + * TODO: + * The results are not predictable. + * JSON1 can not merge moves well. + * See https://github.com/ottypes/json1#limitations. + * > We're missing a conflict for situations + * > when two operations both move the same object to different locations. + * > Currently the left operation will silently 'win' + * > and the other operation's move will be discarded. + * > But this behaviour should be user configurable + */ + const merged = { + number: ['5', '3', '4', '1', '2'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + }); + + describe('duplicated members in array', () => { + it('merging insert operations results in duplicate members', () => { + const base = { + number: ['1', '2'], + }; + + // move + const ours = { + number: ['1', '2', '3'], + }; + + // replace + const theirs = { + number: ['3', '1', '2'], + }; + + // 3 is duplicated. + const merged = { + number: ['3', '1', '2', '3'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merging insert operations results in duplicate members (2)', () => { + const base = { + number: ['1', '2'], + }; + + // move + const ours = { + number: ['1', '2', '3'], + }; + + // replace + const theirs = { + number: ['1', '2', '3'], + }; + + // 3 is duplicated. + const merged = { + number: ['1', '2', '3', '3'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merging insert operations by unique array', () => { + const base = { + unique: ['1', '2'], + }; + + const ours = { + unique: ['1', '2', '3'], + }; + + const theirs = { + unique: ['3', '1', '2'], + }; + + // Result is ['3', '1', '2', '3'] if not unique array. + // ours-diff strategy is applied to remove the first '3'. + const merged = { + unique: ['1', '2', '3'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatchUniqueArray.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual( + merged + ); + }); + + it('merging insert operations by unique array (reverse)', () => { + const base = { + unique: ['1', '2'], + }; + + const ours = { + unique: ['3', '1', '2'], + }; + + const theirs = { + unique: ['1', '2', '3'], + }; + + // Result is ['3', '1', '2', '3'] if not unique array. + // ours-diff strategy is applied to remove the last '3'. + const merged = { + unique: ['3', '1', '2'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatchUniqueArray.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual( + merged + ); + }); + + it('merging insert operations by unique array (2)', () => { + const base = { + unique: ['1', '2'], + }; + + const ours = { + unique: ['1', '2', '3'], + }; + + const theirs = { + unique: ['1', '2', '3'], + }; + + // Result is ['1', '2', '3', '3'] if not unique array. + // ours-diff strategy is applied to remove the last '3'. + const merged = { + unique: ['1', '2', '3'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatchUniqueArray.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual( + merged + ); + }); + + it('merging insert operations by unique array and theirs-diff', () => { + const base = { + unique: ['1', '2'], + }; + + const ours = { + unique: ['1', '2', '3'], + }; + + const theirs = { + unique: ['3', '1', '2'], + }; + + // Result is ['3', '1', '2', '3'] if not unique array. + // theirs-diff strategy is applied to remove the last '3'. + const merged = { + unique: ['3', '1', '2'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect( + jPatchUniqueArray.patch(ours, diffOurs!, theirs, diffTheirs, 'theirs-diff') + ).toStrictEqual(merged); + }); + + it('merging insert operations by unique array and theirs-diff (reverse)', () => { + const base = { + unique: ['1', '2'], + }; + + const ours = { + unique: ['3', '1', '2'], + }; + + const theirs = { + unique: ['1', '2', '3'], + }; + + // Result is ['3', '1', '2', '3'] if not unique array. + // theirs-diff strategy is applied to remove the first '3'. + const merged = { + unique: ['1', '2', '3'], + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect( + jPatchUniqueArray.patch(ours, diffOurs!, theirs, diffTheirs, 'theirs-diff') + ).toStrictEqual(merged); + }); + + it('merging insert operations by unique array in a deep subtree', () => { + const base = { + a: 'a', + b: { + c: 'c', + d: { + e: 'e', + unique: ['1', '2'], + }, + }, + }; + + const ours = { + a: 'a', + b: { + c: 'c', + d: { + e: 'e', + unique: ['1', '2', '3'], + }, + }, + }; + + const theirs = { + a: 'a', + b: { + c: 'c', + d: { + e: 'e', + unique: ['3', '1', '2'], + }, + }, + }; + + // Result is ['3', '1', '2', '3'] if not unique array. + // ours-diff strategy is applied to remove the first '3'. + const merged = { + a: 'a', + b: { + c: 'c', + d: { + e: 'e', + unique: ['1', '2', '3'], + }, + }, + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatchUniqueArray.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual( + merged + ); + }); + + it('multiple unique array appears', () => { + const base = { + unique: ['1', '2'], + b: { + c: 'c', + d: { + e: 'e', + unique: ['1', '2'], + }, + }, + }; + + const ours = { + unique: ['1', '2', '3'], + b: { + c: 'c', + d: { + e: 'e', + unique: ['1', '2', '3'], + }, + }, + }; + + const theirs = { + unique: ['3', '1', '2'], + b: { + c: 'c', + d: { + e: 'e', + unique: ['3', '1', '2'], + }, + }, + }; + + // Result is ['3', '1', '2', '3'] if not unique array. + // ours-diff strategy is applied to remove the first '3'. + const merged = { + unique: ['1', '2', '3'], + b: { + c: 'c', + d: { + e: 'e', + unique: ['1', '2', '3'], + }, + }, + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + + expect(jPatchUniqueArray.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual( + merged + ); + }); + }); + }); + + describe('for object:', () => { + it('returns patch from diff (create)', () => { + const oldDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + }; + const newDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + age2: 'Heijo-kyo', + year2: 710, + current2: false, + }; + + const diff = { + age2: ['Heijo-kyo'], + year2: [710], + current2: [false], + }; + expect(primitiveDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + // keys must be sorted by descendant order + const patch = [ + ['age2', { i: 'Heijo-kyo' }], + ['current2', { i: false }], + ['year2', { i: 710 }], + ]; + + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + }); + + it('patches from diff (create)', () => { + const oldDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + }; + const newDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + age2: 'Heijo-kyo', + year2: 710, + current2: false, + }; + + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('patches from diff (delete)', () => { + const oldDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + }; + const newDoc = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + }; + + expect(jPatch.patch(oldDoc, primitiveDiff.diff(oldDoc, newDoc)!)).toStrictEqual( + newDoc + ); + }); + + it('merges independent changes (create)', () => { + const base = { + _id: 'nara', + age: 'Nara prefecture', + }; + + const ours = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + }; + + const theirs = { + _id: 'nara', + age: 'Nara prefecture', + age2: 'Heijo-kyo', + year2: 710, + current2: false, + }; + + const merged = { + _id: 'nara', + age: 'Nara prefecture', + year: 1887, + current: true, + age2: 'Heijo-kyo', + year2: 710, + current2: false, + }; + + const diffOurs = primitiveDiff.diff(base, ours); + const diffTheirs = primitiveDiff.diff(base, theirs); + + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges independent changes (update)', () => { + const base = { + _id: 'nara', + age: 'Nara prefecture', + deer: 100, + }; + + // The number of deer has increased. + const ours = { + _id: 'nara', + age: 'Nara prefecture', + deer: 1000, + }; + + // The number of deer in Nara was small in the past. + const theirs = { + _id: 'nara', + age: 'Heijo-kyo', + deer: 100, + }; + + // This is correct as a merge result, but incorrect as a schema. + // 'age' and 'deer' are interdependent. + // It must be resolved by user. + const merged = { + _id: 'nara', + age: 'Heijo-kyo', + deer: 1000, + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges conflicted changes (update and remove by ours-diff)', () => { + const base = { + _id: 'nara', + age: 'Nara prefecture', + }; + + const ours = { + _id: 'nara', + age: 'Heijo-kyo', + }; + + const theirs = { + _id: 'nara', + }; + + const merged = { + _id: 'nara', + age: 'Heijo-kyo', + }; + + const diffOurs = primitiveDiff.diff(base, ours); + const diffTheirs = primitiveDiff.diff(base, theirs); + + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges conflicted changes (update by ours-diff)', () => { + // Default strategy is ours-diff + const base = { + _id: 'nara', + age: 'Nara prefecture', + deer: 100, + }; + + const ours = { + _id: 'nara', + age: 'Fujiwara-kyo', + deer: 1000, + }; + + const theirs = { + _id: 'nara', + age: 'Heijo-kyo', + deer: 100, + }; + + const merged = { + _id: 'nara', + age: 'Fujiwara-kyo', + deer: 1000, + }; + + const diffOurs = primitiveDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = primitiveDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + }); + + describe('for text:', () => { + it('applies patch (create)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + const newDoc = { + _id: 'nara', + text: 'abc123def', + }; + + const diff = { + text: [ + `@@ -1,6 +1,9 @@ + abc ++123 + def +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + // keys must be sorted by descendant order + const patch = ['text', { es: [3, '123'] }]; + // const op = editOp(['title'], 'text-unicode', ['My cool blog entry']); + // console.log(op); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('applies patch (replace)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + const newDoc = { + _id: 'nara', + text: 'aebdcf', + }; + + const diff = { + text: [ + `@@ -1,6 +1,6 @@ + a +-bcde ++ebdc + f +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + // keys must be sorted by descendant order + const patch = ['text', { es: [1, { d: 4 }, 'ebdc'] }]; + // const op = editOp(['title'], 'text-unicode', ['My cool blog entry']); + // console.log(op); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('applies patch (move)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdefghijklmnopqrstuvwxyz0123456789', + }; + const newDoc = { + _id: 'nara', + text: 'abcdefg56789hijklmnopqrstuvwxyz01234', + }; + + const diff = { + text: [ + `@@ -1,15 +1,20 @@ + abcdefg ++56789 + hijklmno +@@ -29,13 +29,8 @@ + xyz01234 +-56789 +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const op = editOp(['text'], 'text-unicode', [7, '56789']); + // console.log(op); + const op2 = editOp(['text'], 'text-unicode', [36, { d: 5 }]); + // console.log(op2); + const op3 = [op, op2].reduce(type.compose, null); + // console.log(op3); + + // const op = editOp(['title'], 'text-unicode', ['My cool blog entry']); + // console.log(op); + + expect(jPatch.apply(oldDoc, op3)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (from one character)', () => { + const oldDoc = { + _id: 'nara', + text: ' ', + }; + + const newDoc = { + _id: 'nara', + text: 'abc', + }; + const diff = { + text: [ + `@@ -1 +1,3 @@ +- ++abc +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + const patch = ['text', { es: [{ d: 1 }, 'abc'] }]; + + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (to one character)', () => { + const oldDoc = { + _id: 'nara', + text: 'abc', + }; + + const newDoc = { + _id: 'nara', + text: ' ', + }; + + const diff = { + text: [ + `@@ -1,3 +1 @@ +-abc ++ +`, + 0, + 2, + ], + }; + + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [{ d: 3 }, ' '] }]; + + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (create)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + const newDoc = { + _id: 'nara', + text: 'abc123def', + }; + + const diff = { + text: [ + `@@ -1,6 +1,9 @@ + abc ++123 + def +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [3, '123'] }]; + + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (insert to head of text)', () => { + const oldDoc = { + _id: 'nara', + text: 'abc', + }; + + const newDoc = { + _id: 'nara', + text: '123abc', + }; + const diff = { + text: [ + `@@ -1,3 +1,6 @@ ++123 + abc +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: ['123'] }]; + // expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (insert to middle of text', () => { + const oldDoc = { + _id: 'nara', + text: 'abc', + }; + + const newDoc = { + _id: 'nara', + text: 'ab123c', + }; + const diff = { + text: [ + `@@ -1,3 +1,6 @@ + ab ++123 + c +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [2, '123'] }]; + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (insert to tail of text)', () => { + const oldDoc = { + _id: 'nara', + text: 'abc', + }; + + const newDoc = { + _id: 'nara', + text: 'abc123', + }; + const diff = { + text: [ + `@@ -1,3 +1,6 @@ + abc ++123 +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [3, '123'] }]; + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (delete from head of text)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + + const newDoc = { + _id: 'nara', + text: 'def', + }; + + const diff = { + text: [ + `@@ -1,6 +1,3 @@ +-abc + def +`, + 0, + 2, + ], + }; + + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [{ d: 3 }] }]; + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (delete from middle of text)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + + const newDoc = { + _id: 'nara', + text: 'adef', + }; + + const diff = { + text: [ + `@@ -1,6 +1,4 @@ + a +-bc + def +`, + 0, + 2, + ], + }; + + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [1, { d: 2 }] }]; + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (delete from tail of text)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + + const newDoc = { + _id: 'nara', + text: 'abc', + }; + + const diff = { + text: [ + `@@ -1,6 +1,3 @@ + abc +-def +`, + 0, + 2, + ], + }; + + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [3, { d: 3 }] }]; + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (replace)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + const newDoc = { + _id: 'nara', + text: 'aebdcf', + }; + + const diff = { + text: [ + `@@ -1,6 +1,6 @@ + a +-bcde ++ebdc + f +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [1, { d: 4 }, 'ebdc'] }]; + + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (move)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdefghijklmnopqrstuvwxyz0123456789', + }; + const newDoc = { + _id: 'nara', + text: 'abcdefg56789hijklmnopqrstuvwxyz01234', + }; + + const diff = { + text: [ + `@@ -1,15 +1,20 @@ + abcdefg ++56789 + hijklmno +@@ -29,13 +29,8 @@ + xyz01234 +-56789 +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const op = editOp(['text'], 'text-unicode', [7, '56789']); + // console.log(op); + const op2 = editOp(['text'], 'text-unicode', [36, { d: 5 }]); + // console.log(op2); + const op3 = [op, op2].reduce(type.compose, null); + // console.dir(op3, { depth: 10 }); + + const patch = ['text', { es: [7, '56789', 24, { d: 5 }] }]; + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (escaped)', () => { + // google/diff-match-patch uses encodeURI() + const oldDoc = { + _id: 'nara', + text: '[abc]', + }; + + const newDoc = { + _id: 'nara', + text: `[abc]de`, + }; + + const diff = { + text: [ + `@@ -1,5 +1,7 @@ + %5Babc%5D ++de +`, + 0, + 2, + ], + }; + + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [5, `de`] }]; + + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (not escaped)', () => { + // google/diff-match-patch uses encodeURI() + const oldDoc = { + _id: 'nara', + text: ' ', + }; + + const newDoc = { + _id: 'nara', + text: `AZaz09;,/?:@&=+$-_.!~*'()#`, + }; + + const diff = { + text: [ + `@@ -1 +1,26 @@ +- ++AZaz09;,/?:@&=+$-_.!~*'()# +`, + 0, + 2, + ], + }; + + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + const patch = ['text', { es: [{ d: 1 }, `AZaz09;,/?:@&=+$-_.!~*'()#`] }]; + + expect(jPatch.fromDiff(diff!)).toStrictEqual(patch); + + expect(jPatch.apply(oldDoc, patch)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (two new lines)', () => { + const oldDoc = { + _id: 'nara', + text: 'abcdef', + }; + + const newDoc = { + _id: 'nara', + text: `ab\ncd\nef`, + }; + + const diff = { + text: [ + `@@ -1,6 +1,8 @@ + ab ++%0A + cd ++%0A + ef +`, + 0, + 2, + ], + }; + + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (long text with new lines)', () => { + const oldDoc = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + }; + + const newDoc = { + _id: 'littlewomen', + text: `[Xmas won't be Xmas without any presents,] +grumbled Jo, +lying on the rug. + +[It's so dreadful to be poor!] +sighed Meg, looking down at her old dress.`, + }; + + const diff = { + text: [ + `@@ -1,11 +1,6 @@ +-%22Christ ++%5BX + mas +@@ -12,14 +12,9 @@ + be +-Christ ++X + mas +@@ -34,17 +34,17 @@ + resents, +-%22 ++%5D + %0Agrumble +@@ -48,17 +48,17 @@ + bled Jo, +- ++%0A + lying on +@@ -68,17 +68,18 @@ + e rug. %0A +-%22 ++%0A%5B + It's so +@@ -102,9 +102,9 @@ + oor! +-%22 ++%5D + %0Asig +`, + 0, + 2, + ], + }; + expect(textOTDiff.diff(oldDoc, newDoc)).toStrictEqual(diff); + + // console.dir(jPatch.fromDiff(diff), { depth: 10 }); + + expect(jPatch.patch(oldDoc, diff)).toStrictEqual(newDoc); + }); + + it('returns patch from diff (emoji)', () => { + // google/diff-match-patch uses encodeURI() + const oldDoc = { + _id: 'nara', + text: '😀😃😄😁😆😅', + }; + + const newDoc = { + _id: 'nara', + text: '😀😃a😄😁b😆😅', + }; + + expect(jPatch.patch(oldDoc, textOTDiff.diff(oldDoc, newDoc))).toStrictEqual(newDoc); + }); + + it('merges conflicted text: insert', () => { + const base = { + _id: 'littlewomen', + text: '', + }; + + const ours = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +`, + }; + + const theirs = { + _id: 'littlewomen', + text: `"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + }; + + const merged = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges conflicted text: update and delete', () => { + const base = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + }; + + // update + const ours = { + _id: 'littlewomen', + text: `"Xmas won't be Xmas without any presents," +grumbled Jo, lying on the rug. +"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + }; + + // move + const theirs = { + _id: 'littlewomen', + text: `"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress. +"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug.`, + }; + + // Good result! + const merged = { + _id: 'littlewomen', + text: `"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress. +"Xmas won't be Xmas without any presents," +grumbled Jo, lying on the rug.`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges conflicted text: insert and delete', () => { + const base = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +`, + }; + + const ours = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + }; + + const theirs = { + _id: 'littlewomen', + text: ``, + }; + + const merged = { + _id: 'littlewomen', + text: `"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges conflicted text: update and move', () => { + const base = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +`, + }; + + const ours = { + _id: 'littlewomen', + text: `"Xmas won't be Xmas without any presents," +grumbled Jo, lying on the rug.`, + }; + + const theirs = { + _id: 'littlewomen', + text: ``, + }; + + // ! NOTE: Not good result + const merged = { + _id: 'littlewomen', + text: `XX`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges only the selected property', () => { + const base = { + _id: 'littlewomen', + text: '', + not_merge: '', + }; + + const ours = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +`, + not_merge: 'from ours', + }; + + const theirs = { + _id: 'littlewomen', + text: `"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + not_merge: 'from theirs', + }; + + const merged = { + _id: 'littlewomen', + text: `"Christmas won't be Christmas without any presents," +grumbled Jo, lying on the rug. +"It's so dreadful to be poor!" +sighed Meg, looking down at her old dress.`, + not_merge: 'from ours', + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges non ASCII text', () => { + const base = { + _id: 'wagahai', + author: 'なし', + text: '吾輩は猫である。', + }; + + const ours = { + _id: 'wagahai', + author: '夏目漱石', + text: `吾輩は猫である。名前はまだ無い。`, + }; + + const theirs = { + _id: 'wagahai', + author: '太宰治', + text: `吾輩は犬である。`, + }; + + const merged = { + _id: 'wagahai', + author: '夏目漱石', + text: `吾輩は犬である。名前はまだ無い。`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges non ASCII text 2', () => { + const base = { + _id: 'wagahai', + text: '吾輩は猫である。', + }; + + const ours = { + _id: 'wagahai', + text: `吾輩は猫だよ。`, + }; + + const theirs = { + _id: 'wagahai', + text: `吾輩は犬である。`, + }; + + const merged = { + _id: 'wagahai', + text: `吾輩は犬だよ。`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges non ASCII text 3', () => { + const base = { + _id: 'wagahai', + text: '吾輩は猫である。', + }; + + const ours = { + _id: 'wagahai', + text: `吾輩は猫だよ。`, + }; + + const theirs = { + _id: 'wagahai', + text: `吾輩は犬だよ。`, + }; + + // ! NOTE: Not good result + const merged = { + _id: 'wagahai', + text: `吾輩はだよ犬だよ。`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges non ASCII text', () => { + const base = { + _id: 'wagahai', + author: 'なし', + text: '吾輩は猫である。', + }; + + const ours = { + _id: 'wagahai', + author: '夏目漱石', + text: `吾輩は猫である。名前はまだ無い。`, + }; + + const theirs = { + _id: 'wagahai', + author: '太宰治', + text: `吾輩は犬である。`, + }; + + const merged = { + _id: 'wagahai', + author: '夏目漱石', + text: `吾輩は犬である。名前はまだ無い。`, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + }); + + describe('merge nested object:', () => { + it('merges simple structure', () => { + const base = { + geometry: { + height: 300, + }, + }; + + const ours = { + geometry: { + height: 374, + }, + }; + + const theirs = { + geometry: { + height: 310, + }, + }; + + const merged = { + geometry: { + height: 374, + }, + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merges complex structure', () => { + const base = { + condition: { + locked: false, + }, + geometry: { + height: 300, + width: 434, + x: 70, + y: 70, + z: 2, + }, + style: { + backgroundColor: '#ffffff', + opacity: 1, + uiColor: '#f5f5f5', + zoom: 0.85, + }, + _id: 'note/n01FCXJV361VCX5SEEY45V8X604/c01FCXJV1DPAJZ7X6M8YYF17TZF', + }; + + const ours = { + condition: { + locked: false, + }, + geometry: { + height: 374, + width: 324, + x: 64, + y: 80, + z: 2, + }, + style: { + backgroundColor: '#fff8d0', + opacity: 1, + uiColor: '#f5eec8', + zoom: 0.85, + }, + _id: 'note/n01FCXJV361VCX5SEEY45V8X604/c01FCXJV1DPAJZ7X6M8YYF17TZF', + }; + + const theirs = { + condition: { + locked: false, + }, + geometry: { + height: 300, + width: 434, + x: 250, + y: 54, + z: 160, + }, + style: { + backgroundColor: '#ffffff', + opacity: 1, + uiColor: '#f5f5f5', + zoom: 0.85, + }, + _id: 'note/n01FCXJV361VCX5SEEY45V8X604/c01FCXJV1DPAJZ7X6M8YYF17TZF', + }; + + const merged = { + condition: { + locked: false, + }, + geometry: { + height: 374, + width: 324, + x: 64, + y: 80, + z: 160, + }, + style: { + backgroundColor: '#fff8d0', + opacity: 1, + uiColor: '#f5eec8', + zoom: 0.85, + }, + _id: 'note/n01FCXJV361VCX5SEEY45V8X604/c01FCXJV1DPAJZ7X6M8YYF17TZF', + }; + + const diffOurs = textOTDiff.diff(base, ours); + // console.log(diffOurs); + const diffTheirs = textOTDiff.diff(base, theirs); + // console.log(diffTheirs); + const patchOurs = jPatch.fromDiff(diffOurs!); + // console.log(patchOurs); + const patchTheirs = jPatch.fromDiff(diffTheirs!); + // console.log(patchTheirs); + + expect(jPatch.patch(ours, diffOurs!, theirs, diffTheirs)).toStrictEqual(merged); + }); + + it('merge complex structure including delete operation', () => { + const docOurs = { + _id: 'note/n2021-10-12-15-30-30-_YFSS58F/c2021-12-06-05-54-52-GE43E73', + condition: { locked: false }, + date: { createdDate: '2021-12-06 05:54:52', modifiedDate: '2021-12-15 00:31:28' }, + geometry: { height: 900, width: 461, x: 706, y: 80, z: 5804 }, + label: { + enabled: false, + status: 'closedLabel', + text: 'foo', + }, + style: { backgroundColor: '#ffdd9e', opacity: 1, uiColor: '#f5d498', zoom: 0.85 }, + }; + + const docTheirs = {}; + + const newDoc = { + _id: 'note/n2021-10-12-15-30-30-_YFSS58F/c2021-12-06-05-54-52-GE43E73', + condition: { locked: false }, + date: { createdDate: '2021-12-06 05:54:52', modifiedDate: '2021-12-15 00:31:28' }, + geometry: { height: 900, width: 461, x: 1459, y: 180, z: 5953 }, + label: { + enabled: false, + status: 'openedSticker', + x: 1562, + y: 144, + height: 92, + width: 329, + text: 'foo bar', + }, + style: { backgroundColor: '#fff8d0', opacity: 1, uiColor: '#fff8d0', zoom: 0.85 }, + }; + + const diffOurs = { + date: { modifiedDate: ['2021-12-15 00:31:17', '2021-12-15 00:31:28'] }, + label: { + height: [64, 0, 0], + width: [461, 0, 0], + x: [706, 0, 0], + y: [80, 0, 0], + zoom: [0.85, 0, 0], + }, + }; + const diffTheirs = { + date: { modifiedDate: ['2021-12-15 00:31:17', '2021-12-15 07:36:11'] }, + geometry: { x: [706, 1459], y: [80, 180], z: [5804, 5953] }, + label: { + height: [64, 92], + status: ['closedLabel', 'openedSticker'], + text: ['foo', 'foo bar'], + width: [461, 329], + x: [706, 1562], + y: [80, 144], + }, + style: { backgroundColor: ['#ffdd9e', '#fff8d0'], uiColor: ['#f5d498', '#fff8d0'] }, + }; + + expect(jPatch.patch(docOurs, diffOurs, docTheirs, diffTheirs)).toStrictEqual(newDoc); + }); + }); +}); diff --git a/test/remote_repository/remote_repository.test.ts b/test/remote_repository/remote_repository.test.ts new file mode 100644 index 00000000..36220b60 --- /dev/null +++ b/test/remote_repository/remote_repository.test.ts @@ -0,0 +1,302 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test remote_repository.ts + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import { Octokit } from '@octokit/rest'; +import expect from 'expect'; +import fs from 'fs-extra'; +import { Err } from '../../src/error'; +import { NETWORK_RETRY, NETWORK_RETRY_INTERVAL } from '../../src/const'; +import { + createRemoteRepository, + destroyRemoteRepository, + removeRemoteRepositories, +} from '../remote_utils'; +import { RemoteRepository } from '../../src/remote/remote_repository'; + +const reposPrefix = 'test_remote_repository___'; +const localDir = `./test/database_remote_repository`; + +let idCounter = 0; +const serialId = () => { + return `${reposPrefix}${idCounter++}`; +}; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +maybe(' RemoteRepository', () => { + const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + + before(async () => { + // Remove remote + await removeRemoteRepositories(reposPrefix); + }); + + describe('create()', () => { + it('throws InvalidAuthenticationTypeError', () => { + const remoteURL = remoteURLBase + serialId(); + expect(() => { + const repo = new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + // @ts-ignore + type: 'gitlab', + }, + }); + }); + }); + + it('creates a remote repository on GitHub by personal access token', async () => { + const remoteURL = remoteURLBase + serialId(); + const octokit = new Octokit({ + auth: token, + }); + const urlArray = remoteURL.split('/'); + const owner = urlArray[urlArray.length - 2]; + const repo = urlArray[urlArray.length - 1]; + + await new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + }, + }).create(); + await expect(octokit.repos.listBranches({ owner, repo })).resolves.not.toThrowError(); + }); + + it('creates a remote repository by url which ends with .git.', async () => { + let remoteURL = remoteURLBase + serialId(); + const octokit = new Octokit({ + auth: token, + }); + const urlArray = remoteURL.split('/'); + const owner = urlArray[urlArray.length - 2]; + const repo = urlArray[urlArray.length - 1]; + + remoteURL += '.git'; + await new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + }, + }).create(); + await expect(octokit.repos.listBranches({ owner, repo })).resolves.not.toThrowError(); + }); + + it('creates a private remote repository', async () => { + const remoteURL = remoteURLBase + serialId(); + const octokit = new Octokit({ + auth: token, + }); + const urlArray = remoteURL.split('/'); + const owner = urlArray[urlArray.length - 2]; + const repo = urlArray[urlArray.length - 1]; + + await new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + private: true, + }, + }).create(); + const repos = await octokit.repos.get({ owner, repo }); + expect(repos.data.private).toBeTruthy(); + }); + + it('creates a private remote repository by default', async () => { + const remoteURL = remoteURLBase + serialId(); + const octokit = new Octokit({ + auth: token, + }); + const urlArray = remoteURL.split('/'); + const owner = urlArray[urlArray.length - 2]; + const repo = urlArray[urlArray.length - 1]; + + await new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + }, + }).create(); + const repos = await octokit.repos.get({ owner, repo }); + expect(repos.data.private).toBeTruthy(); + }); + + it('creates a public remote repository', async () => { + const remoteURL = remoteURLBase + serialId(); + const octokit = new Octokit({ + auth: token, + }); + const urlArray = remoteURL.split('/'); + const owner = urlArray[urlArray.length - 2]; + const repo = urlArray[urlArray.length - 1]; + + await new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + private: false, + }, + }).create(); + const repos = await octokit.repos.get({ owner, repo }); + expect(repos.data.private).toBeFalsy(); + }); + + it('throws UndefinedPersonalAccessTokenError()', async () => { + const remoteURL = remoteURLBase + serialId(); + + await expect( + new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: undefined, + }, + }).create() + ).rejects.toThrowError(Err.UndefinedPersonalAccessTokenError); + }); + + it('throws PersonalAccessTokenForAnotherAccountError()', async () => { + const readonlyURL = 'https://github.com/sosuisen/' + serialId(); + + await expect( + new RemoteRepository({ + remoteUrl: readonlyURL, + connection: { + type: 'github', + personalAccessToken: token, // This is valid but for another account. + }, + }).create() + ).rejects.toThrowError(Err.PersonalAccessTokenForAnotherAccountError); + }); + + it(`throws CannotConnectRemoteRepositoryError() with ${NETWORK_RETRY} retries`, async () => { + const remoteURL = remoteURLBase + serialId(); + await createRemoteRepository(remoteURL); + + const error = await new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + }, + }) + .create() + .catch(err => err); + expect(error).toBeInstanceOf(Err.CannotConnectRemoteRepositoryError); + // This may be tested by using sinon.spy + expect((error as Err.CannotConnectRemoteRepositoryError).retry).toBe(NETWORK_RETRY); + }); + + it('throws AuthenticationTypeNotAllowCreateRepositoryError()', async () => { + const remoteURL = remoteURLBase + serialId(); + + await expect( + new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'none', + }, + }).create() + ).rejects.toThrowError(Err.AuthenticationTypeNotAllowCreateRepositoryError); + }); + }); + + describe('destroy()', () => { + it('removes a remote repository on GitHub by personal access token', async () => { + const remoteURL = remoteURLBase + serialId(); + + await createRemoteRepository(remoteURL); + const octokit = new Octokit({ + auth: token, + }); + const urlArray = remoteURL.split('/'); + const owner = urlArray[urlArray.length - 2]; + const repo = urlArray[urlArray.length - 1]; + + await destroyRemoteRepository(remoteURL); + + await expect(octokit.repos.listBranches({ owner, repo })).rejects.toThrowError(); + }); + + it('throws UndefinedPersonalAccessTokenError()', async () => { + const remoteURL = remoteURLBase + serialId(); + + await expect( + new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: undefined, + }, + }).destroy() + ).rejects.toThrowError(Err.UndefinedPersonalAccessTokenError); + }); + + it(`throws CannotConnectRemoteRepositoryError() with ${NETWORK_RETRY_INTERVAL} retries`, async () => { + const remoteURL = remoteURLBase + serialId(); + + const error = await new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'github', + personalAccessToken: token, + }, + }) + .destroy() + .catch(err => err); + expect(error).toBeInstanceOf(Err.CannotConnectRemoteRepositoryError); + expect((error as Err.CannotConnectRemoteRepositoryError).retry).toBe(NETWORK_RETRY); + }); + + it('throws AuthenticationTypeNotAllowCreateRepositoryError()', async () => { + const remoteURL = remoteURLBase + serialId(); + + await expect( + new RemoteRepository({ + remoteUrl: remoteURL, + connection: { + type: 'none', + }, + }).destroy() + ).rejects.toThrowError(Err.AuthenticationTypeNotAllowCreateRepositoryError); + }); + }); +}); diff --git a/test/remote_utils.ts b/test/remote_utils.ts index 21ed0698..534a31ed 100644 --- a/test/remote_utils.ts +++ b/test/remote_utils.ts @@ -1,23 +1,32 @@ /* eslint-disable @typescript-eslint/naming-convention */ import fs from 'fs-extra'; import { Octokit } from '@octokit/rest'; +import git from 'isomorphic-git'; import sinon from 'sinon'; import expect from 'expect'; -import nodegit from '@sosuisen/nodegit'; +import { TLogLevelName } from 'tslog'; +import httpClient from 'isomorphic-git/http/node'; +import { createCredentialCallback, push } from '../src/plugin/remote-isomorphic-git'; +import { Sync } from '../src/remote/sync'; +import { textToJsonDoc } from '../src/crud/blob'; import { ChangedFileDelete, ChangedFileInsert, ChangedFileUpdate, + DatabaseOpenResult, DeleteResult, JsonDoc, PutResult, RemoteOptions, Schema, + SerializeFormat, + SerializeFormatLabel, } from '../src/types'; import { SyncInterface } from '../src/types_sync'; import { GitDocumentDB } from '../src/git_documentdb'; -import { FILE_REMOVE_TIMEOUT, JSON_EXT } from '../src/const'; +import { FILE_REMOVE_TIMEOUT, GIT_DOCUMENTDB_METADATA_DIR } from '../src/const'; import { RemoteRepository } from '../src/remote/remote_repository'; +import { SerializeFormatJSON } from '../src/serialize_format'; const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; @@ -57,13 +66,14 @@ export function getCommitInfo (resultOrMessage: (PutResult | DeleteResult | stri */ export function getChangedFileInsert ( newDoc: JsonDoc, - newResult: PutResult | DeleteResult + newResult: PutResult | DeleteResult, + serializeFormat: SerializeFormat = new SerializeFormatJSON() ): ChangedFileInsert { return { operation: 'insert', new: { _id: newDoc!._id, - name: newDoc!._id + JSON_EXT, + name: newDoc!._id + serializeFormat.extension(newDoc), fileOid: newResult!.fileOid, type: 'json', doc: newDoc, @@ -75,20 +85,21 @@ export function getChangedFileUpdate ( oldDoc: JsonDoc, oldResult: PutResult | DeleteResult, newDoc: JsonDoc, - newResult: PutResult | DeleteResult + newResult: PutResult | DeleteResult, + serializeFormat: SerializeFormat = new SerializeFormatJSON() ): ChangedFileUpdate { return { operation: 'update', old: { _id: oldDoc!._id, - name: oldDoc!._id + JSON_EXT, + name: oldDoc!._id + serializeFormat.extension(oldDoc!), fileOid: oldResult!.fileOid, type: 'json', doc: oldDoc!, }, new: { _id: newDoc!._id, - name: newDoc!._id + JSON_EXT, + name: newDoc!._id + serializeFormat.extension(newDoc), fileOid: newResult!.fileOid, type: 'json', doc: newDoc, @@ -98,13 +109,14 @@ export function getChangedFileUpdate ( export function getChangedFileDelete ( oldDoc: JsonDoc, - oldResult: PutResult | DeleteResult + oldResult: PutResult | DeleteResult, + serializeFormat: SerializeFormat = new SerializeFormatJSON() ): ChangedFileDelete { return { operation: 'delete', old: { _id: oldDoc!._id, - name: oldDoc!._id + JSON_EXT, + name: oldDoc!._id + serializeFormat.extension(oldDoc), fileOid: oldResult!.fileOid, type: 'json', doc: oldDoc, @@ -114,13 +126,14 @@ export function getChangedFileDelete ( export function getChangedFileInsertBySHA ( newDoc: JsonDoc, - newFileSHA: string + newFileSHA: string, + serializeFormat: SerializeFormat = new SerializeFormatJSON() ): ChangedFileInsert { return { operation: 'insert', new: { _id: newDoc!._id, - name: newDoc!._id + JSON_EXT, + name: newDoc!._id + serializeFormat.extension(newDoc), fileOid: newFileSHA, type: 'json', doc: newDoc, @@ -132,20 +145,21 @@ export function getChangedFileUpdateBySHA ( oldDoc: JsonDoc, oldFileSHA: string, newDoc: JsonDoc, - newFileSHA: string + newFileSHA: string, + serializeFormat: SerializeFormat = new SerializeFormatJSON() ): ChangedFileUpdate { return { operation: 'update', old: { _id: oldDoc!._id, - name: oldDoc!._id + JSON_EXT, + name: oldDoc!._id + serializeFormat.extension(oldDoc!), fileOid: oldFileSHA, type: 'json', doc: oldDoc!, }, new: { _id: newDoc!._id, - name: newDoc!._id + JSON_EXT, + name: newDoc!._id + serializeFormat.extension(newDoc), fileOid: newFileSHA, type: 'json', doc: newDoc, @@ -155,13 +169,14 @@ export function getChangedFileUpdateBySHA ( export function getChangedFileDeleteBySHA ( oldDoc: JsonDoc, - oldFileSHA: string + oldFileSHA: string, + serializeFormat: SerializeFormat = new SerializeFormatJSON() ): ChangedFileDelete { return { operation: 'delete', old: { _id: oldDoc!._id, - name: oldDoc!._id + JSON_EXT, + name: oldDoc!._id + serializeFormat.extension(oldDoc), fileOid: oldFileSHA, type: 'json', doc: oldDoc, @@ -169,21 +184,63 @@ export function getChangedFileDeleteBySHA ( }; } +export async function resetRemoteCommonRepository ( + remoteURLBase: string, + localDir: string, + localId: () => string, + remoteId: () => string +): Promise { + const dbName = remoteId(); + + // Create empty repository + const db: GitDocumentDB = new GitDocumentDB({ + dbName: 'common_' + localId(), + localDir, + }); + await db.open(); + const remoteURL = remoteURLBase + remoteId(); + const options: RemoteOptions = { + remoteUrl: remoteURL, + connection: { type: 'github', personalAccessToken: token }, + }; + const sync = new Sync(db, options); + await createGitRemote(db.workingDir, remoteURL, sync.remoteName); + + const cred = createCredentialCallback(options); + const pushOption: any = { + fs, + dir: db.workingDir, + http: httpClient, + url: remoteURL, + ref: 'main', + remote: 'origin', + remoteRef: 'main', + force: true, // force overwrite by empty repository + onAuth: cred, + }; + const res = await git.push(pushOption).catch(err => err); + + await db.destroy().catch(e => {}); +} + export async function createDatabase ( remoteURLBase: string, localDir: string, - serialId: () => string, + localId: () => string, + remoteId: () => string, options?: RemoteOptions, - schema?: Schema + schema?: Schema, + logLevel: TLogLevelName = 'info' ): Promise<[GitDocumentDB, SyncInterface]> { - const remoteURL = remoteURLBase + serialId(); + const remoteURL = remoteURLBase + remoteId(); - const dbNameA = serialId(); + const dbNameA = localId(); const dbA: GitDocumentDB = new GitDocumentDB({ dbName: dbNameA, localDir, schema, + logLevel, }); options ??= { remoteUrl: remoteURL, @@ -191,7 +248,6 @@ export async function createDatabase ( includeCommits: true, }; options.remoteUrl ??= remoteURL; - options.connection ??= { type: 'github', personalAccessToken: token }; options.includeCommits ??= true; await dbA.open(); @@ -204,18 +260,21 @@ export async function createDatabase ( export async function createClonedDatabases ( remoteURLBase: string, localDir: string, - serialId: () => string, + localId: () => string, + remoteId: () => string, options?: RemoteOptions, - logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' + logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal', + serialize: SerializeFormatLabel = 'json' ): Promise<[GitDocumentDB, GitDocumentDB, SyncInterface, SyncInterface]> { - const remoteURL = remoteURLBase + serialId(); + const remoteURL = remoteURLBase + remoteId(); - const dbNameA = serialId(); + const dbNameA = localId(); const dbA: GitDocumentDB = new GitDocumentDB({ dbName: dbNameA, localDir, logLevel: logLevel ?? 'info', + serialize, }); options ??= { remoteUrl: remoteURL, @@ -225,20 +284,18 @@ export async function createClonedDatabases ( options.remoteUrl ??= remoteURL; options.connection ??= { type: 'github', personalAccessToken: token }; options.includeCommits ??= true; - await dbA.open(); await dbA.sync(options); - - const dbNameB = serialId(); + const dbNameB = localId(); const dbB: GitDocumentDB = new GitDocumentDB({ dbName: dbNameB, localDir, logLevel: logLevel ?? 'info', + serialize, }); // Clone dbA await dbB.open(); await dbB.sync(options); - const remoteA = dbA.getSync(remoteURL); const remoteB = dbB.getSync(remoteURL); @@ -269,10 +326,7 @@ export const destroyRemoteRepository = async (remoteURL: string) => { }, }) .destroy() - .catch(err => { - console.debug('Cannot delete: ' + remoteURL); - console.debug(err); - }); + .catch(() => {}); }; export async function removeRemoteRepositories (reposPrefix: string) { @@ -296,6 +350,7 @@ export async function removeRemoteRepositories (reposPrefix: string) { const repo = urlArray[1]; return repo.startsWith(reposPrefix); } + return false; }) ); // console.log(` - Got ${reposArray.length} repositories`); @@ -333,50 +388,45 @@ export const compareWorkingDirAndBlobs = async ( ): Promise => { const files = listFiles(gitDDB, gitDDB.workingDir); - const currentIndex = await gitDDB.repository()?.refreshIndex(); - const entryCount = currentIndex!.entryCount() - 1; // Reduce by 1 due to '.gitddb/lib_version' + const entries: string[] = await git.walk({ + fs, + dir: gitDDB.workingDir, + trees: [git.STAGE()], + // @ts-ignore + // eslint-disable-next-line complexity + map: async function (fullDocPath, [entry]) { + if (fullDocPath.startsWith(GIT_DOCUMENTDB_METADATA_DIR)) return; + if ((await entry?.type()) === 'blob') { + return fullDocPath; + } + }, + }); + // console.log('# check count: fromFiles: ' + files.length + ', fromIndex: ' + entryCount); - if (files.length !== entryCount) { + if (files.length !== entries.length) { return false; } - /** Basic type (loose or packed) of any Git object. - // https://github.com/libgit2/libgit2/blob/HEAD/include/git2/types.h - typedef enum { - GIT_OBJECT_ANY = -2, // Object can be any of the following - GIT_OBJECT_INVALID = -1, // Object is invalid. - GIT_OBJECT_COMMIT = 1, // A commit object. - GIT_OBJECT_TREE = 2, // A tree (directory listing) object. - GIT_OBJECT_BLOB = 3, // A file revision object. - GIT_OBJECT_TAG = 4, // An annotated tag object. - GIT_OBJECT_OFS_DELTA = 6, // A delta, base is given by an offset. - GIT_OBJECT_REF_DELTA = 7, // A delta, base is given by object id. - } git_object_t; - */ for (const file of files) { // console.log('# check:' + file); - // Type 3 means BLOB - // @ts-ignore - // eslint-disable-next-line no-await-in-loop - const hashFromFile = await nodegit.Odb.hashfile( - gitDDB.workingDir + '/' + file, - 3 - ).catch((err: Error) => console.log(err)); - // console.log(' - fromFile: ' + hashFromFile.tostrS()); - // Does index include blob? - const hashFromIndex = currentIndex?.getByPath(file).id; - // console.log(' - fromIndex: ' + hashFromIndex!.tostrS()); - if (!hashFromIndex?.equal(hashFromFile)) { + if (!entries.includes(file)) { return false; } + + // eslint-disable-next-line no-await-in-loop + const buf = await fs.readFile(gitDDB.workingDir + '/' + file)!; + const data = Uint8Array.from(buf); + // eslint-disable-next-line no-await-in-loop + const { oid } = await git.hashBlob({ object: data }); + // Does blob exist? // eslint-disable-next-line no-await-in-loop - const blob = await gitDDB - .repository() - ?.getBlob(hashFromIndex!) + const readBlobResult = await git + .readBlob({ fs, dir: gitDDB.workingDir, oid }) .catch((err: Error) => console.log(err)); - if (!blob || blob?.rawsize() === 0) { + + if (readBlobResult === undefined) { return false; } // console.log(' - rawSize:' + blob?.rawsize()); @@ -384,10 +434,21 @@ export const compareWorkingDirAndBlobs = async ( return true; }; -export const getWorkingDirDocs = (gitDDB: GitDocumentDB) => { +export const getWorkingDirDocs = ( + gitDDB: GitDocumentDB, + serializeFormat: SerializeFormat = new SerializeFormatJSON() +) => { return listFiles(gitDDB, gitDDB.workingDir).map(filepath => { + if (serializeFormat.format === 'front-matter') { + const txt = fs.readFileSync(gitDDB.workingDir + '/' + filepath, { encoding: 'utf8' }); + const [, extension] = filepath.match(/.+(\..+?)$/)!; + const doc = textToJsonDoc(txt, serializeFormat, extension); + doc._id = serializeFormat.removeExtension(filepath); + return doc; + } + const doc = fs.readJSONSync(gitDDB.workingDir + '/' + filepath); - doc._id = filepath.replace(new RegExp(JSON_EXT + '$'), ''); + doc._id = serializeFormat.removeExtension(filepath); return doc; }); }; @@ -403,7 +464,36 @@ export const destroyDBs = async (DBs: GitDocumentDB[]) => { /* throws FileRemoveTimeoutError */ }) ) - ).catch(() => {}); + ).catch(err => { + console.log(err); + }); await clock.tickAsync(FILE_REMOVE_TIMEOUT); clock.restore(); }; + +export async function createGitRemote ( + localDir: string, + remoteUrl: string, + remoteName: string +) { + await git.addRemote({ + fs, + dir: localDir, + remote: remoteName, + url: remoteUrl, + }); + /* + await git.setConfig({ + fs, + dir: localDir, + path: `remote.${remoteName}.url`, + value: remoteUrl, + }); + await git.setConfig({ + fs, + dir: localDir, + path: `remote.${remoteName}.fetch`, + value: `+refs/heads/*:refs/remotes/${remoteName}/*`, + }); +*/ +} diff --git a/test/task_queue.test.ts b/test/task_queue.test.ts index 243e6351..56417392 100644 --- a/test/task_queue.test.ts +++ b/test/task_queue.test.ts @@ -13,22 +13,104 @@ import expect from 'expect'; import fs from 'fs-extra'; import { Logger } from 'tslog'; import { GitDocumentDB } from '../src/git_documentdb'; -import { createDatabase, destroyDBs, removeRemoteRepositories } from './remote_utils'; import { sleep } from '../src/utils'; import { TaskQueue } from '../src/task_queue'; -import { TaskMetadata } from '../src/types'; +import { ColoredLogger, TaskMetadata } from '../src/types'; +import { Err } from '../src/error'; const ulid = monotonicFactory(); const monoId = () => { return ulid(Date.now()); }; -const reposPrefix = 'test_task_queue___'; const localDir = './test/database_task_queue'; -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; +const tsLogger = new Logger({ + name: monoId(), + minLevel: 'info', + displayDateTime: false, + displayFunctionName: false, + displayFilePath: 'hidden', +}); + +const logger: ColoredLogger = { + silly: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (colorTag !== undefined) { + tsLogger.silly(colorTag()`${mes}`); + } + else { + tsLogger.silly(mes); + } + }, + debug: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (colorTag !== undefined) { + tsLogger.debug(colorTag()`${mes}`); + } + else { + tsLogger.debug(mes); + } + }, + trace: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (colorTag !== undefined) { + tsLogger.trace(colorTag()`${mes}`); + } + else { + tsLogger.trace(mes); + } + }, + info: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (colorTag !== undefined) { + tsLogger.info(colorTag()`${mes}`); + } + else { + tsLogger.info(mes); + } + }, + warn: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (colorTag !== undefined) { + tsLogger.warn(colorTag()`${mes}`); + } + else { + tsLogger.warn(mes); + } + }, + error: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (colorTag !== undefined) { + tsLogger.error(colorTag()`${mes}`); + } + else { + tsLogger.error(mes); + } + }, + fatal: ( + mes: string, + colorTag?: () => (literals: TemplateStringsArray, ...placeholders: any[]) => string + ) => { + if (colorTag !== undefined) { + tsLogger.fatal(colorTag()`${mes}`); + } + else { + tsLogger.fatal(mes); + } + }, }; beforeEach(function () { @@ -45,6 +127,349 @@ after(() => { }); describe('', () => { + describe('debounce', () => { + it('debounces consecutive puts to the same _id', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + debounceTime: 3000, + logLevel: 'trace', + }); + await gitDDB.open(); + let skippedTask00 = false; + gitDDB.put({ _id: 'a', name: '0' }, { taskId: '0' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask00 = true; + }); + let skippedTask01 = false; + gitDDB.put({ _id: 'a', name: '1' }, { taskId: '1' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask01 = true; + }); + let skippedTask02 = false; + gitDDB.put({ _id: 'a', name: '2' }, { taskId: '2' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask02 = true; + }); + let skippedTask03 = false; + gitDDB.put({ _id: 'a', name: '3' }, { taskId: '3' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask03 = true; + }); + await sleep(4000); + expect(skippedTask00).toBeTruthy(); + expect(skippedTask01).toBeTruthy(); + expect(skippedTask02).toBeTruthy(); + expect(skippedTask03).toBeFalsy(); + + const json = await gitDDB.get('a'); + expect(json!.name).toEqual('3'); + + await gitDDB.destroy(); + }); + + it('debounces a lot of consecutive puts to the same _id', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + debounceTime: 3000, + logLevel: 'trace', + }); + await gitDDB.open(); + let skippedTask00 = false; + gitDDB.put({ _id: 'a', name: '0' }, { taskId: '0' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask00 = true; + }); + await sleep(4000); + + const putter: Promise[] = []; + const validResult: (boolean | Record)[] = []; + for (let i = 1; i < 25; i++) { + putter.push( + gitDDB.put({ _id: 'a', name: `${i}` }, { taskId: `${i}` }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + } + putter.push( + gitDDB.put({ _id: 'a', name: '25' }, { taskId: '25' }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push({ _id: 'a' }); + + const results = await Promise.all(putter); + + expect(skippedTask00).toBeFalsy(); + + expect(results).toMatchObject(validResult); + + const json = await gitDDB.get('a'); + expect(json!.name).toEqual('25'); + + await gitDDB.destroy(); + }); + + it('debounces a lot of consecutive puts to the mixed _ids', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + debounceTime: 3000, + logLevel: 'trace', + }); + await gitDDB.open(); + let skippedTaskA00 = false; + gitDDB.put({ _id: 'a', name: '0' }, { taskId: 'a0' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTaskA00 = true; + }); + let skippedTaskB00 = false; + gitDDB.put({ _id: 'b', name: '0' }, { taskId: 'b0' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTaskB00 = true; + }); + let skippedTaskC00 = false; + gitDDB.put({ _id: 'c', name: '0' }, { taskId: 'c0' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTaskC00 = true; + }); + await sleep(4000); + + const putter: Promise[] = []; + const validResult: (boolean | Record)[] = []; + for (let i = 1; i < 50; i++) { + putter.push( + gitDDB.put({ _id: 'a', name: `${i}` }, { taskId: `a${i}` }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + putter.push( + gitDDB.put({ _id: 'b', name: `${i}` }, { taskId: `b${i}` }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + putter.push( + gitDDB.put({ _id: 'c', name: `${i}` }, { taskId: `c${i}` }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + } + putter.push( + gitDDB.put({ _id: 'a', name: '50' }, { taskId: 'a50' }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push({ _id: 'a' }); + putter.push( + gitDDB.put({ _id: 'b', name: '50' }, { taskId: 'b50' }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push({ _id: 'b' }); + putter.push( + gitDDB.put({ _id: 'c', name: '50' }, { taskId: 'c50' }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push({ _id: 'c' }); + + const results = await Promise.all(putter); + + expect(skippedTaskA00).toBeFalsy(); + expect(skippedTaskB00).toBeFalsy(); + expect(skippedTaskC00).toBeFalsy(); + + expect(results).toMatchObject(validResult); + + const jsonA = await gitDDB.get('a'); + expect(jsonA!.name).toEqual('50'); + const jsonB = await gitDDB.get('b'); + expect(jsonB!.name).toEqual('50'); + const jsonC = await gitDDB.get('c'); + expect(jsonC!.name).toEqual('50'); + + await gitDDB.destroy(); + }); + + it('debounces a lot of consecutive puts mixed with a delete command', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + debounceTime: 3000, + logLevel: 'trace', + }); + await gitDDB.open(); + + const putter: Promise[] = []; + const validResult: (boolean | Record)[] = []; + for (let i = 0; i < 9; i++) { + putter.push( + gitDDB.put({ _id: 'a', name: `${i}` }, { taskId: `${i}` }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + } + + // put task just before delete task will be executed. + putter.push( + gitDDB.put({ _id: 'a', name: `9` }, { taskId: `9` }).catch(err => { + if (err instanceof Err.TaskCancelError) return false; + }) + ); + validResult.push({ _id: 'a' }); + + // Delete + putter.push(gitDDB.delete('a')); + validResult.push({ + _id: 'a', + }); + + for (let i = 10; i < 20; i++) { + putter.push( + gitDDB.put({ _id: 'a', name: `${i}` }, { taskId: `${i}` }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + } + putter.push( + gitDDB.put({ _id: 'a', name: '20' }, { taskId: '20' }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push({ _id: 'a' }); + + const results = await Promise.all(putter); + + expect(results).toMatchObject(validResult); + + const json = await gitDDB.get('a'); + expect(json!.name).toEqual('20'); + + await gitDDB.destroy(); + }); + + it('debounces a lot of consecutive puts mixed with an insert command', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + debounceTime: 3000, + logLevel: 'trace', + }); + await gitDDB.open(); + + const putter: Promise[] = []; + const validResult: (boolean | undefined | Record)[] = []; + for (let i = 0; i < 9; i++) { + putter.push( + gitDDB.put({ _id: 'a', name: `${i}` }, { taskId: `${i}` }).catch(err => { + if (err instanceof Err.TaskCancelError) return true; + }) + ); + validResult.push(true); + } + + // put task just before insert task will be executed. + putter.push( + gitDDB.put({ _id: 'a', name: `9` }, { taskId: `9` }).catch(err => { + if (err instanceof Err.TaskCancelError) return false; + }) + ); + validResult.push({ _id: 'a' }); + + // Insert throws error + putter.push(gitDDB.insert({ _id: 'a', name: '10' }).catch(() => undefined)); + validResult.push(undefined); + + const results = await Promise.all(putter); + + expect(results).toMatchObject(validResult); + + const json = await gitDDB.get('a'); + expect(json!.name).toEqual('9'); + + await gitDDB.destroy(); + }); + + it('Set different debounceTime in each collection', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + debounceTime: 3000, + logLevel: 'trace', + }); + await gitDDB.open(); + const colA = gitDDB.collection('a', { debounceTime: 7000 }); + const colB = gitDDB.collection('b', { debounceTime: 5000 }); + const colC = gitDDB.collection('c', { debounceTime: 1000 }); + + const result: string[] = []; + colA + .put({ _id: 'a1' }) + .then(() => result.push('a1')) + .catch(() => {}); + colB + .put({ _id: 'b1' }) + .then(() => result.push('b1')) + .catch(() => {}); + colC + .put({ _id: 'c1' }) + .then(() => result.push('c1')) + .catch(() => {}); + colC + .put({ _id: 'c1' }) + .then(() => result.push('c2')) + .catch(() => {}); + await sleep(10000); + + expect(result).toEqual(['c2', 'b1', 'a1']); + await gitDDB.destroy(); + }); + + it('Collection debounceTime will be overwritten by method debounceTime', async () => { + const dbName = monoId(); + const gitDDB: GitDocumentDB = new GitDocumentDB({ + dbName, + localDir, + debounceTime: 3000, + logLevel: 'trace', + }); + await gitDDB.open(); + let skippedTask00 = false; + gitDDB.put({ _id: 'a', name: '0' }, { taskId: '0' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask00 = true; + }); + let skippedTask01 = false; + gitDDB.put({ _id: 'a', name: '1' }, { taskId: '1' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask01 = true; + }); + let skippedTask02 = false; + gitDDB.put({ _id: 'a', name: '2' }, { taskId: '2' }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask02 = true; + }); + + let skippedTask03 = false; + gitDDB.put({ _id: 'a', name: '3' }, { taskId: '3', debounceTime: 0 }).catch(err => { + if (err instanceof Err.TaskCancelError) skippedTask03 = true; + }); + await sleep(1000); + + expect(skippedTask00).toBeTruthy(); + expect(skippedTask01).toBeTruthy(); + expect(skippedTask02).toBeTruthy(); + expect(skippedTask03).toBeFalsy(); + + const json = await gitDDB.get('a'); + expect(json!.name).toEqual('3'); + + await gitDDB.destroy(); + }); + }); + it('increments statistics: put', async () => { const dbName = monoId(); const gitDDB: GitDocumentDB = new GitDocumentDB({ @@ -149,16 +574,8 @@ describe('', () => { }); it('returns newTaskId', () => { - const dbName = monoId(); - const taskQueue = new TaskQueue( - new Logger({ - name: dbName, - minLevel: 'info', - displayDateTime: false, - displayFunctionName: false, - displayFilePath: 'hidden', - }) - ); + const taskQueue = new TaskQueue(logger); + taskQueue.start(); // e.g.) 01BX5ZZKBKACTAV9WEVGEMMVRZ let prevId = ''; for (let i = 0; i < 30; i++) { @@ -170,6 +587,9 @@ describe('', () => { } prevId = id; } + + // clear() must be called to clear setInterval + taskQueue.stop(); }); it('clear() statistics', async () => { @@ -193,7 +613,7 @@ describe('', () => { sync: 0, cancel: 0, }); - gitDDB.taskQueue.clear(); + gitDDB.taskQueue.stop(); expect(gitDDB.taskQueue.currentStatistics()).toEqual({ put: 0, insert: 0, @@ -429,70 +849,3 @@ describe('', () => { await gitDDB.destroy(); }); }); - -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe(' remote', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - it('increments statistics: push', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - // The first push in open() - expect(dbA.taskQueue.currentStatistics().push).toBe(1); - - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - expect(dbA.taskQueue.currentStatistics().push).toBe(2); - - await destroyDBs([dbA]); - }); - - it('increments statistics: sync', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - expect(dbA.taskQueue.currentStatistics().sync).toBe(0); - - await syncA.trySync(); - expect(dbA.taskQueue.currentStatistics().sync).toBe(1); - - await destroyDBs([dbA]); - }); - - it('clear() statistics', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId); - - await syncA.trySync(); - expect(dbA.taskQueue.currentStatistics()).toEqual({ - put: 0, - insert: 0, - update: 0, - delete: 0, - push: 1, - sync: 1, - cancel: 0, - }); - dbA.taskQueue.clear(); - expect(dbA.taskQueue.currentStatistics()).toEqual({ - put: 0, - insert: 0, - update: 0, - delete: 0, - push: 0, - sync: 0, - cancel: 0, - }); - await destroyDBs([dbA]); - }); -}); diff --git a/test_intg/3way_merge_ot.test.ts b/test_intg/3way_merge_ot.test.ts deleted file mode 100644 index b4887893..00000000 --- a/test_intg/3way_merge_ot.test.ts +++ /dev/null @@ -1,752 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test Operational Transformation in 3-way merge - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import { GitDocumentDB } from '../src/git_documentdb'; -import { - Schema, - SyncResultMergeAndPush, - SyncResultResolveConflictsAndPush, -} from '../src/types'; -import { - compareWorkingDirAndBlobs, - createClonedDatabases, - createDatabase, - destroyDBs, - getChangedFileDelete, - getChangedFileInsert, - getChangedFileUpdateBySHA, - getCommitInfo, - getWorkingDirDocs, - removeRemoteRepositories, -} from '../test/remote_utils'; -import { JSON_EXT } from '../src/const'; - -const reposPrefix = 'test_3way_merge_ot___'; -const localDir = `./test_intg/database_3way_merge_ot`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak of getCommitLogs() - // fs.removeSync(path.resolve(localDir)); -}); - -// This test needs environment variables: -// - GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -// - GITDDB_personalAccessToken: A personal access token of your GitHub account -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe('intg: <3way_merge_ot>', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - /** - * before: - * dbA : jsonA1 jsonA2 - * dbB : jsonB1 jsonB3 - * after : mergedJson jsonA2 jsonB3 - * - * 3-way merge: - * mergedJson: 4 - Conflict. Accept ours (insert-merge) - * jsonA2: 1 - Accept theirs (insert) - * jsonB3: 2 - Accept ours (insert) - */ - it('resolves case 1 - Accept theirs (insert), case 2 - Accept ours (insert), case 4 - Conflict. Accept ours (insert-merge)', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours-diff', - } - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA', a: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB', b: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - const mergedJson = { _id: '1', name: 'fromB', a: 'fromA', b: 'fromB' }; - - // B puts a new file - const jsonB3 = { _id: '3', name: 'fromB' }; - const putResultB3 = await dbB.put(jsonB3); - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - - const mergedDoc = await dbB.getFatDoc('1.json'); - - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - putResultA2, - `resolve: 1${JSON_EXT}(insert-merge,${mergedDoc!.fileOid.substr(0, 7)},ours-diff)`, - ]), - remote: getCommitInfo([ - putResultB1, - putResultB3, - `resolve: 1${JSON_EXT}(insert-merge,${mergedDoc!.fileOid.substr(0, 7)},ours-diff)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(2); - expect(syncResult1.changes.local).toEqual( - expect.arrayContaining([ - getChangedFileUpdateBySHA( - jsonB1, - putResultB1.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - getChangedFileInsert(jsonA2, putResultA2), - ]) - ); - - expect(syncResult1.changes.remote.length).toBe(2); - expect(syncResult1.changes.remote).toEqual( - expect.arrayContaining([ - getChangedFileUpdateBySHA( - jsonA1, - putResultA1.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - getChangedFileInsert(jsonB3, putResultB3), - ]) - ); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: mergedDoc, - strategy: 'ours-diff', - operation: 'insert-merge', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([mergedJson, jsonA2, jsonB3]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([mergedJson, jsonA2, jsonB3]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: - * dbA : jsonA1 - * dbB : jsonB1 - * after : jsonA1 - * - * 3-way merge: - * jsonA1: 5 - Conflict. Accept theirs (insert) - */ - it('resolves case 5 - Conflict. Accept theirs (insert)', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'theirs-diff', - } - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B puts the same file - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - const mergedJson = { _id: '1', name: 'fromA' }; - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - - const mergedDoc = await dbB.getFatDoc('1.json'); - - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1, - `resolve: 1${JSON_EXT}(insert-merge,${mergedDoc!.fileOid.substr( - 0, - 7 - )},theirs-diff)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(insert-merge,${mergedDoc!.fileOid.substr( - 0, - 7 - )},theirs-diff)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdateBySHA( - jsonB1, - putResultB1!.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - ]); - - expect(syncResult1.changes.remote.length).toBe(0); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: mergedDoc, - strategy: 'theirs-diff', - operation: 'insert-merge', - }, - ]); - expect(getWorkingDirDocs(dbA)).toEqual([jsonA1]); - expect(getWorkingDirDocs(dbB)).toEqual([jsonA1]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : -jsonA1 - * result: - * - * '+' means update - * - * 3-way merge: - * jsonA1: 8 - Conflict. Accept ours (delete) - */ - it('resolves case 8 - Conflict. Accept ours (delete)', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours-diff', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A updates and pushes - const jsonA1dash = { _id: '1', name: 'updated' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B removes and syncs - const deleteResultB1 = await dbB.delete(jsonA1); - - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(delete,${deleteResultB1.fileOid.substr(0, 7)},ours-diff)`, - ]), - remote: getCommitInfo([ - deleteResultB1, - `resolve: 1${JSON_EXT}(delete,${deleteResultB1.fileOid.substr(0, 7)},ours-diff)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(0); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileDelete(jsonA1dash, putResultA1dash), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: deleteResultB1.fileOid, - type: 'json', - doc: jsonA1, - }, - strategy: 'ours-diff', - operation: 'delete', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : -jsonA1 jsonA2 - * dbB : jsonB1 - * result: jsonB1 jsonA2 - * - * 3-way merge: - * jsonB1: 11 - Conflict. Accept ours (update) - * jsonA2: 1 - Accept theirs (insert) - */ - it('resolves case 11 - Conflict. Accept ours (update), case 1 - Accept theirs (insert), ', async () => { - const [dbA, syncA] = await createDatabase(remoteURLBase, localDir, serialId, { - conflictResolutionStrategy: 'ours-diff', - }); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync(syncA.options); - - // A removes the old file and puts a new file - const deleteResultA1 = await dbA.delete(jsonA1); - const jsonA2 = { _id: '2', name: 'fromA' }; - const putResultA2 = await dbA.put(jsonA2); - await syncA.tryPush(); - - // B updates the old file and syncs - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - deleteResultA1, - putResultA2, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours-diff)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(update,${putResultB1.fileOid.substr(0, 7)},ours-diff)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([getChangedFileInsert(jsonA2, putResultA2)]); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([getChangedFileInsert(jsonB1, putResultB1)]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: { - _id: '1', - name: '1.json', - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - strategy: 'ours-diff', - operation: 'update', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([jsonB1, jsonA2]); - - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([jsonB1, jsonA2]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : mergedJson - * - * 3-way merge: - * mergedJson:17 - Conflict. Accept theirs (update-merge) - */ - it('resolves case 17 - Conflict. Accept theirs (update-merge)', async () => { - const schema: Schema = { - json: { plainTextProperties: { name: true } }, - }; - const [dbA, syncA] = await createDatabase( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'theirs-diff', - }, - schema - ); - // A puts and pushes - const jsonA1 = { _id: '1', name: 'Hello, world!' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - schema, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync({ - ...syncA.options, - conflictResolutionStrategy: 'theirs-diff', - }); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'Hello' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'Hello, world! Hello, Nara!' }; - const putResultB1 = await dbB.put(jsonB1); - - const mergedJson = { _id: '1', name: 'Hello Hello, Nara!' }; - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - - const mergedDoc = await dbB.getFatDoc('1.json'); - - expect(syncResult1.action).toBe('resolve conflicts and push'); - expect(syncResult1.commits).toMatchObject({ - local: getCommitInfo([ - putResultA1dash, - `resolve: 1${JSON_EXT}(update-merge,${mergedDoc!.fileOid.substr( - 0, - 7 - )},theirs-diff)`, - ]), - remote: getCommitInfo([ - putResultB1, - `resolve: 1${JSON_EXT}(update-merge,${mergedDoc!.fileOid.substr( - 0, - 7 - )},theirs-diff)`, - ]), - }); - expect(syncResult1.changes.local.length).toBe(1); - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdateBySHA( - jsonB1, - putResultB1.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - ]); - - expect(syncResult1.changes.remote.length).toBe(1); - expect(syncResult1.changes.remote).toEqual([ - getChangedFileUpdateBySHA( - jsonA1dash, - putResultA1dash.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - ]); - - expect(syncResult1.conflicts.length).toEqual(1); - expect(syncResult1.conflicts).toEqual([ - { - fatDoc: mergedDoc, - strategy: 'theirs-diff', - operation: 'update-merge', - }, - ]); - // Conflict occurs on 1.json - - expect(getWorkingDirDocs(dbB)).toEqual([mergedJson]); - // Sync dbA - const syncResult2 = (await syncA.trySync()) as SyncResultMergeAndPush; - expect(getWorkingDirDocs(dbA)).toEqual([mergedJson]); - - await expect(compareWorkingDirAndBlobs(dbA)).resolves.toBeTruthy(); - await expect(compareWorkingDirAndBlobs(dbB)).resolves.toBeTruthy(); - - await destroyDBs([dbA, dbB]); - }); - - describe('plaintext-OT Type', () => { - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : mergedJson - * - * 3-way merge: - * mergedJson:17 - Conflict. Accept theirs (update-merge) - */ - it('add text', async () => { - const schema: Schema = { - json: { plainTextProperties: { name: true } }, - }; - const [dbA, syncA] = await createDatabase( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours-diff', - }, - schema - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'Nara and Kyoto' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - schema, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync({ - ...syncA.options, - conflictResolutionStrategy: 'ours-diff', - }); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'Hello, Nara and Kyoto' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'Nara and Kyoto and Osaka' }; - const putResultB1 = await dbB.put(jsonB1); - - const mergedJson = { _id: '1', name: 'Hello, Nara and Kyoto and Osaka' }; - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - - const mergedDoc = await dbB.getFatDoc('1.json'); - - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdateBySHA( - jsonB1, - putResultB1.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - ]); - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : mergedJson - * - * 3-way merge: - * mergedJson:17 - Conflict. Accept theirs (update-merge) - */ - it('move text', async () => { - const schema: Schema = { - json: { plainTextProperties: { name: true } }, - }; - const [dbA, syncA] = await createDatabase( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours-diff', - }, - schema - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'Nara Osaka Kyoto Nagoya' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - schema, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync({ - ...syncA.options, - conflictResolutionStrategy: 'ours-diff', - }); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'Osaka Kyoto Nara Nagoya' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'Kyoto Nara Osaka Nagoya' }; - const putResultB1 = await dbB.put(jsonB1); - - const mergedJson = { _id: '1', name: 'Kyoto Osaka Nara Nagoya' }; - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - - const mergedDoc = await dbB.getFatDoc('1.json'); - - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdateBySHA( - jsonB1, - putResultB1.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - ]); - await destroyDBs([dbA, dbB]); - }); - - /** - * before: jsonA1 - * dbA : +jsonA1 - * dbB : jsonB1 - * after : mergedJson - * - * 3-way merge: - * mergedJson:17 - Conflict. Accept theirs (update-merge) - */ - it('bad result', async () => { - const schema: Schema = { - json: { plainTextProperties: { name: true } }, - }; - const [dbA, syncA] = await createDatabase( - remoteURLBase, - localDir, - serialId, - { - conflictResolutionStrategy: 'ours-diff', - }, - schema - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'Nara Kyoto' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - schema, - }); - // Clone dbA - await dbB.open(); - const syncB = await dbB.sync({ - ...syncA.options, - conflictResolutionStrategy: 'ours-diff', - }); - - // A puts and pushes - const jsonA1dash = { _id: '1', name: 'Nara Kamo' }; - const putResultA1dash = await dbA.put(jsonA1dash); - await syncA.tryPush(); - - // B puts - const jsonB1 = { _id: '1', name: 'Kyoto Nara' }; - const putResultB1 = await dbB.put(jsonB1); - - // ! Bad result. Best result is 'Kyoto Nara Kamo' - const mergedJson = { _id: '1', name: 'Kyoto ama' }; - - // It will occur conflict on id 1.json. - const syncResult1 = (await syncB.trySync()) as SyncResultResolveConflictsAndPush; - - const mergedDoc = await dbB.getFatDoc('1.json'); - - expect(syncResult1.changes.local).toEqual([ - getChangedFileUpdateBySHA( - jsonB1, - putResultB1.fileOid, - mergedJson, - mergedDoc!.fileOid - ), - ]); - await destroyDBs([dbA, dbB]); - }); - }); -}); diff --git a/test_intg/README.md b/test_intg/README.md deleted file mode 100644 index daf6f6b7..00000000 --- a/test_intg/README.md +++ /dev/null @@ -1 +0,0 @@ -# Integration Test \ No newline at end of file diff --git a/test_intg/on_sync_event.test.ts b/test_intg/on_sync_event.test.ts deleted file mode 100644 index 8ca73e3f..00000000 --- a/test_intg/on_sync_event.test.ts +++ /dev/null @@ -1,422 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test Operational Transformation in 3-way merge - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import { Err } from '../src/error'; -import { SyncResult, SyncResultFastForwardMerge, TaskMetadata } from '../src/types'; -import { - createClonedDatabases, - destroyDBs, - getChangedFileInsert, - getCommitInfo, - removeRemoteRepositories, -} from '../test/remote_utils'; -import { sleep } from '../src/utils'; -import { GitDocumentDB } from '../src/git_documentdb'; - -const reposPrefix = 'test_on_sync_event___'; -const localDir = `./test_intg/database_on_sync_event`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak of getCommitLogs() - // fs.removeSync(path.resolve(localDir)); -}); - -// This test needs environment variables: -// - GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -// - GITDDB_personalAccessToken: A personal access token of your GitHub account -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -maybe('intg: ', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - describe('onSyncEvent', () => { - it('with remoteURL', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B syncs - let result: SyncResultFastForwardMerge | undefined; - let changeTaskId = ''; - - dbB.onSyncEvent( - syncB.remoteURL, - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - result = syncResult as SyncResultFastForwardMerge; - changeTaskId = taskMetadata.taskId; - } - ); - let complete = false; - let endTaskId = ''; - dbB.onSyncEvent(syncB.remoteURL, 'complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(result!.action).toBe('fast-forward merge'); - - expect(result!.commits).toMatchObject({ - local: getCommitInfo([putResult1]), - }); - - expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); - - expect(changeTaskId).toBe(endTaskId); - - await destroyDBs([dbA, dbB]); - }); - - it('with remoteURL throws UndefinedSyncError', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - expect(() => { - dbA.onSyncEvent('https://test.example.com', 'change', () => {}); - }).toThrowError(Err.UndefinedSyncError); - }); - - it('with sync', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // B syncs - let result: SyncResultFastForwardMerge | undefined; - let changeTaskId = ''; - - dbB.onSyncEvent( - syncB, - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - result = syncResult as SyncResultFastForwardMerge; - changeTaskId = taskMetadata.taskId; - } - ); - let complete = false; - let endTaskId = ''; - dbB.onSyncEvent(syncB, 'complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(result!.action).toBe('fast-forward merge'); - - expect(result!.commits).toMatchObject({ - local: getCommitInfo([putResult1]), - }); - - expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); - - expect(changeTaskId).toBe(endTaskId); - - await destroyDBs([dbA, dbB]); - }); - }); - - describe('offSyncEvent', () => { - it('with remoteURL', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; - dbB.onSyncEvent(syncB.remoteURL, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(1); - dbB.offSyncEvent(syncB.remoteURL, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(0); - - await destroyDBs([dbA, dbB]); - }); - - it('with remoteURL throws UndefinedSyncError', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - expect(() => { - dbA.offSyncEvent('https://test.example.com', 'change', () => {}); - }).toThrowError(Err.UndefinedSyncError); - }); - - it('with sync', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; - dbB.onSyncEvent(syncB, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(1); - dbB.offSyncEvent(syncB, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(0); - - await destroyDBs([dbA, dbB]); - }); - }); -}); - -maybe('intg: ', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - describe('onSyncEvent', () => { - it('with remoteURL', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - const colA = dbA.collection('col'); - const colB = dbB.collection('col'); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await colA.put(jsonA1); - await syncA.tryPush(); - - // B syncs - let result: SyncResultFastForwardMerge | undefined; - let changeTaskId = ''; - - colB.onSyncEvent( - syncB.remoteURL, - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - result = syncResult as SyncResultFastForwardMerge; - changeTaskId = taskMetadata.taskId; - } - ); - let complete = false; - let endTaskId = ''; - colB.onSyncEvent(syncB.remoteURL, 'complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(result!.action).toBe('fast-forward merge'); - - expect(result!.commits).toMatchObject({ - local: getCommitInfo([putResult1]), - }); - - expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); - - expect(changeTaskId).toBe(endTaskId); - - await destroyDBs([dbA, dbB]); - }); - - it('with remoteURL throws UndefinedSyncError', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - const colA = dbA.collection('col'); - expect(() => { - colA.onSyncEvent('https://test.example.com', 'change', () => {}); - }).toThrowError(Err.UndefinedSyncError); - }); - - it('with sync', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - const colA = dbA.collection('col'); - const colB = dbB.collection('col'); - - // A puts and pushes - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResult1 = await colA.put(jsonA1); - await syncA.tryPush(); - - // B syncs - let result: SyncResultFastForwardMerge | undefined; - let changeTaskId = ''; - - colB.onSyncEvent( - syncB, - 'change', - (syncResult: SyncResult, taskMetadata: TaskMetadata) => { - result = syncResult as SyncResultFastForwardMerge; - changeTaskId = taskMetadata.taskId; - } - ); - let complete = false; - let endTaskId = ''; - colB.onSyncEvent(syncB, 'complete', (taskMetadata: TaskMetadata) => { - complete = true; - endTaskId = taskMetadata.taskId; - }); - await syncB.trySync(); - - // eslint-disable-next-line no-unmodified-loop-condition - while (!complete) { - // eslint-disable-next-line no-await-in-loop - await sleep(1000); - } - - expect(result!.action).toBe('fast-forward merge'); - - expect(result!.commits).toMatchObject({ - local: getCommitInfo([putResult1]), - }); - - expect(result!.changes.local).toEqual([getChangedFileInsert(jsonA1, putResult1)]); - - expect(changeTaskId).toBe(endTaskId); - - await destroyDBs([dbA, dbB]); - }); - }); - - describe('offSyncEvent', () => { - it('with remoteURL', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - const colB = dbB.collection('col'); - const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; - colB.onSyncEvent(syncB.remoteURL, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(1); - colB.offSyncEvent(syncB.remoteURL, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(0); - - await destroyDBs([dbA, dbB]); - }); - - it('with remoteURL throws UndefinedSyncError', async () => { - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const colA = dbA.collection('col'); - - expect(() => { - colA.offSyncEvent('https://test.example.com', 'change', () => {}); - }).toThrowError(Err.UndefinedSyncError); - }); - - it('with sync', async () => { - const [dbA, dbB, syncA, syncB] = await createClonedDatabases( - remoteURLBase, - localDir, - serialId - ); - - const colB = dbB.collection('col'); - - const callback = (syncResult: SyncResult, taskMetadata: TaskMetadata) => {}; - colB.onSyncEvent(syncB, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(1); - colB.offSyncEvent(syncB, 'change', callback); - expect(syncB.eventHandlers.change.length).toBe(0); - - await destroyDBs([dbA, dbB]); - }); - }); -}); diff --git a/test_intg/sync_lifecycle.test.ts b/test_intg/sync_lifecycle.test.ts deleted file mode 100644 index 3c522a7d..00000000 --- a/test_intg/sync_lifecycle.test.ts +++ /dev/null @@ -1,1003 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -/** - * GitDocumentDB - * Copyright (c) Hidekazu Kubota - * - * This source code is licensed under the Mozilla Public License Version 2.0 - * found in the LICENSE file in the root directory of this source tree. - */ - -/** - * Test lifecycle of synchronization (open, sync, tryPush, trySync) - * by using GitHub Personal Access Token - * These tests create a new repository on GitHub if not exists. - */ -import path from 'path'; -import fs from 'fs-extra'; -import expect from 'expect'; -import sinon from 'sinon'; -import { Sync } from '../src/remote/sync'; -import { GitDocumentDB } from '../src/git_documentdb'; -import { RemoteOptions, SyncResultPush } from '../src/types'; -import { Err } from '../src/error'; -import { sleep } from '../src/utils'; -import { - destroyDBs, - getChangedFileInsert, - getChangedFileUpdate, - removeRemoteRepositories, -} from '../test/remote_utils'; -import { JSON_EXT, MINIMUM_SYNC_INTERVAL, NETWORK_RETRY } from '../src/const'; -import { pushWorker } from '../src/remote/push_worker'; -import { syncWorker } from '../src/remote/sync_worker'; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const pushWorker_module = require('../src/remote/push_worker'); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const syncWorker_module = require('../src/remote/sync_worker'); - -const reposPrefix = 'test_sync_lifecycle___'; -const localDir = `./test_intg/database_sync_lifecycle`; - -let idCounter = 0; -const serialId = () => { - return `${reposPrefix}${idCounter++}`; -}; - -// Use sandbox to restore stub and spy in parallel mocha tests -let sandbox: sinon.SinonSandbox; -beforeEach(function () { - // @ts-ignore - console.log(`... ${this.currentTest.fullTitle()}`); - sandbox = sinon.createSandbox(); -}); - -afterEach(function () { - sandbox.restore(); -}); - -before(() => { - fs.removeSync(path.resolve(localDir)); -}); - -after(() => { - // It may throw error due to memory leak with UnfetchedCommitExistsError - // fs.removeSync(path.resolve(localDir)); -}); - -// GITDDB_GITHUB_USER_URL: URL of your GitHub account -// e.g.) https://github.com/foo/ -const maybe = - process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN - ? describe - : describe.skip; - -// Test lifecycle of Sync (open, sync, tryPush, trySync) -maybe('intg Sync', () => { - const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') - ? process.env.GITDDB_GITHUB_USER_URL - : process.env.GITDDB_GITHUB_USER_URL + '/'; - const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; - - before(async () => { - await removeRemoteRepositories(reposPrefix); - }); - - /** - * Initialize synchronization by open() with remoteURL - * Initialize means creating local and remote repositories by using a remoteUrl - */ - describe('initialized by open():', () => { - it('getSync() returns an instance of Sync.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - expect(syncA.remoteURL).toBe(remoteURL); - destroyDBs([dbA]); - }); - - it('unregisterRemote() removes an instance of Sync.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - await dbA.sync(options); - dbA.removeSync(remoteURL); - expect(dbA.getSync(remoteURL)).toBeUndefined(); - destroyDBs([dbA]); - }); - - it.skip('getRemoteURLs() returns sync', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - logLevel: 'trace', - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - await dbA.sync(options); - const remoteURL2 = remoteURLBase + serialId(); - const options2: RemoteOptions = { - remoteUrl: remoteURL2, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.sync(options2); - expect(dbA.getRemoteURLs()).toEqual([remoteURL, remoteURL2]); - destroyDBs([dbA]); - }); - - /** - * Basics: A is empty, creates remote, puts data; B is empty, clones the remote - */ - describe('After dbA created remote repository, dbB clones it.', () => { - it('dbA and dbB have the same document.', async () => { - const remoteURL = remoteURLBase + serialId(); - - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - await syncA.tryPush(); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - await dbB.sync(options); - - await expect(dbB.get(jsonA1._id)).resolves.toMatchObject(jsonA1); - - await destroyDBs([dbA, dbB]); - }); - - it('Race condition of two tryPush() calls throws UnfetchedCommitExistsError.', async () => { - const remoteURL = remoteURLBase + serialId(); - - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - const syncB = await dbB.sync(options); - const jsonB1 = { _id: '1', name: 'fromB' }; - await dbB.put(jsonB1); - - await expect(Promise.all([syncA.tryPush(), syncB.tryPush()])).rejects.toThrowError( - Err.UnfetchedCommitExistsError - ); - - await destroyDBs([dbA, dbB]); - }); - - it('Ordered condition of two tryPush() calls throws UnfetchedCommitExistsError.', async () => { - const remoteURL = remoteURLBase + serialId(); - - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - const syncB = await dbB.sync(options); - const jsonB1 = { _id: '1', name: 'fromB' }; - await dbB.put(jsonB1); - - await syncA.tryPush(); - await expect(syncB.tryPush()).rejects.toThrowError(Err.UnfetchedCommitExistsError); - - await destroyDBs([dbA, dbB]); - }); - - it('Updating the same document results [resolve conflict and push] action.', async () => { - const remoteURL = remoteURLBase + serialId(); - - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - const syncB = await dbB.sync(options); - - const jsonA1 = { _id: '1', name: 'fromA' }; - const putResultA1 = await dbA.put(jsonA1); - await syncA.tryPush(); - - // The same id - const jsonB1 = { _id: '1', name: 'fromB' }; - const putResultB1 = await dbB.put(jsonB1); - - await expect(syncB.trySync()).resolves.toMatchObject({ - action: 'resolve conflicts and push', - changes: { - local: [], - remote: [getChangedFileUpdate(jsonA1, putResultA1, jsonB1, putResultB1)], - }, - conflicts: [ - { - fatDoc: { - _id: jsonB1._id, - name: jsonB1._id + JSON_EXT, - fileOid: putResultB1.fileOid, - type: 'json', - doc: jsonB1, - }, - operation: 'insert-merge', - strategy: 'ours-diff', - }, - ], - }); - - await destroyDBs([dbA, dbB]); - }); - }); - - /** - * Repetitive Sync (live) - */ - describe('Repetitive Sync (live)', () => { - it('starts and pushes after interval when called from open() with live option.', async () => { - const remoteURL = remoteURLBase + serialId(); - - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const interval = MINIMUM_SYNC_INTERVAL; - const options: RemoteOptions = { - remoteUrl: remoteURL, - live: true, - syncDirection: 'both', - interval, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - - expect(syncA.options.live).toBeTruthy(); - expect(syncA.options.interval).toBe(interval); - - // Wait live sync() - while (dbA.taskQueue.currentStatistics().sync === 0) { - // eslint-disable-next-line no-await-in-loop - await sleep(500); - } - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - await dbB.sync(options); - await expect(dbB.get(jsonA1._id)).resolves.toMatchObject(jsonA1); - - await destroyDBs([dbA, dbB]); - }); - - it('stops by pause()', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const interval = MINIMUM_SYNC_INTERVAL; - const options: RemoteOptions = { - remoteUrl: remoteURL, - live: true, - syncDirection: 'both', - interval, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - - expect(syncA.options.live).toBeTruthy(); - const count = dbA.taskQueue.currentStatistics().sync; - syncA.pause(); - await sleep(interval * 2); - expect(syncA.options.live).toBeFalsy(); - expect(dbA.taskQueue.currentStatistics().sync).toBe(count); - - await destroyDBs([dbA]); - }); - - it('pause() and resume()', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const interval = MINIMUM_SYNC_INTERVAL; - const options: RemoteOptions = { - remoteUrl: remoteURL, - live: true, - syncDirection: 'both', - interval, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - - expect(syncA.options.live).toBeTruthy(); - const count = dbA.taskQueue.currentStatistics().sync; - expect(syncA.pause()).toBeTruthy(); - expect(syncA.pause()).toBeFalsy(); // ignored - - await sleep(interval * 2); - expect(syncA.options.live).toBeFalsy(); - expect(dbA.taskQueue.currentStatistics().sync).toBe(count); - - expect(syncA.resume()).toBeTruthy(); - expect(syncA.resume()).toBeFalsy(); // ignored - await sleep(interval * 2); - expect(syncA.options.live).toBeTruthy(); - expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThan(count); - - await destroyDBs([dbA]); - }); - - it('stops by gitDDB.close()', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const interval = MINIMUM_SYNC_INTERVAL; - const options: RemoteOptions = { - remoteUrl: remoteURL, - live: true, - syncDirection: 'both', - interval, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - - expect(syncA.options.live).toBeTruthy(); - const count = dbA.taskQueue.currentStatistics().sync; - await dbA.close(); - - syncA.resume(); // resume() must be ignored after close(); - - await sleep(interval * 2); - expect(syncA.options.live).toBeFalsy(); - expect(dbA.taskQueue.currentStatistics().sync).toBe(count); - - await destroyDBs([dbA]); - }); - - it('changes interval when resume() is called with new interval.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const interval = MINIMUM_SYNC_INTERVAL; - const options: RemoteOptions = { - remoteUrl: remoteURL, - live: true, - syncDirection: 'both', - interval, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - - expect(syncA.options.interval).toBe(interval); - - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - // Wait live sync() - while (dbA.taskQueue.currentStatistics().sync === 0) { - // eslint-disable-next-line no-await-in-loop - await sleep(500); - } - syncA.pause(); - - const jsonA2 = { _id: '2', name: 'fromA' }; - await dbA.put(jsonA2); - - const currentCount = dbA.taskQueue.currentStatistics().sync; - // Change interval - syncA.resume({ - interval: interval * 3, - }); - expect(syncA.options.interval).toBe(interval * 3); - await sleep(interval); - // Check count before next sync() - expect(dbA.taskQueue.currentStatistics().sync).toBe(currentCount); - - await destroyDBs([dbA]); - }); - - it('repeats trySync() automatically.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - const interval = MINIMUM_SYNC_INTERVAL; - const options: RemoteOptions = { - remoteUrl: remoteURL, - live: true, - syncDirection: 'both', - interval, - connection: { type: 'github', personalAccessToken: token }, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - - await sleep(interval * 5); - expect(dbA.taskQueue.currentStatistics().sync).toBeGreaterThanOrEqual(3); - - await destroyDBs([dbA]); - }); - }); - - /** - * Retry sync - */ - describe('Failed sync', () => { - it('retries tryPush() in init() after connection errors, and fails.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'push', - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = new Sync(dbA, options); - const stubNet = sandbox.stub(sync, 'canNetworkConnection'); - stubNet.resolves(false); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.rejects(); - - await expect(sync.init(dbA.repository()!)).rejects.toThrowError(); - - expect(stubPush.callCount).toBe(NETWORK_RETRY + 1); - - await destroyDBs([dbA]); - }); - - it('retries tryPush() in init() after connection errors, and succeeds.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'push', - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = new Sync(dbA, options); - const stubNet = sandbox.stub(sync, 'canNetworkConnection'); - stubNet.resolves(false); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.onFirstCall().rejects(); - const syncResultPush: SyncResultPush = { - action: 'push', - changes: { - remote: [], - }, - }; - - // Call pushWorker which is not spied by Sinon - stubPush.onSecondCall().callsFake(async () => { - stubPush.restore(); - return await pushWorker(dbA, sync, { - label: 'sync', - taskId: 'myTaskId', - }); - }); - const syncResult = await sync.init(dbA.repository()!); - expect(syncResult).toEqual(syncResultPush); - - expect(stubPush.callCount).toBe(2); - - await destroyDBs([dbA]); - }); - - it('does not retry tryPush() in init() after error except connection errors and resolvable errors.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'push', - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = new Sync(dbA, options); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.rejects(); - - // Call pushWorker which is not spied by Sinon - stubPush.onSecondCall().callsFake(async () => { - stubPush.restore(); - return await pushWorker(dbA, sync, { - label: 'sync', - taskId: 'myTaskId', - }); - }); - - await expect(sync.init(dbA.repository()!)).rejects.toThrowError( - Err.PushWorkerError - ); - - expect(stubPush.callCount).toBe(1); - - await destroyDBs([dbA]); - }); - - it('retries trySync() in init() after connection errors, and fails.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'both', - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = await dbA.sync(options); - - const stubNet = sandbox.stub(sync, 'canNetworkConnection'); - stubNet.resolves(false); - - const stubSync = sandbox.stub(syncWorker_module, 'syncWorker'); - stubSync.rejects(); - - // sync has already been initialized, so will run trySync() - await expect(sync.init(dbA.repository()!)).rejects.toThrowError(); - - expect(stubSync.callCount).toBe(NETWORK_RETRY + 1); - - await destroyDBs([dbA]); - }); - - it('retries trySync() in init() after connection errors, and succeeds.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'both', - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = await dbA.sync(options); - - const stubNet = sandbox.stub(sync, 'canNetworkConnection'); - stubNet.resolves(false); - - const stubSync = sandbox.stub(syncWorker_module, 'syncWorker'); - stubSync.onFirstCall().rejects(); - - // Call pushWorker which is not spied by Sinon - stubSync.onSecondCall().callsFake(async () => { - stubSync.restore(); - return await syncWorker(dbA, sync, { - label: 'sync', - taskId: 'myTaskId', - }); - }); - - const jsonA1 = { _id: '1', name: 'profile01' }; - const putResult = await dbA.put(jsonA1); - const syncResultPush: SyncResultPush = { - action: 'push', - changes: { - remote: [getChangedFileInsert(jsonA1, putResult)], - }, - }; - - await expect(sync.init(dbA.repository()!)).resolves.toEqual(syncResultPush); - - expect(stubSync.callCount).toBe(2); - - await destroyDBs([dbA]); - }); - - it('retries trySync() in init() after resolvable errors, and succeeds.', async () => { - /** - * After race condition of trySync() throws Error, - * db retries trySync() and resolves the problems automatically. - */ - const remoteURL = remoteURLBase + serialId(); - - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - // Set retry interval to 0ms - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - retryInterval: 0, - }; - await dbA.open(); - const syncA = await dbA.sync(options); - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - const syncB = await dbB.sync(options); - const jsonB1 = { _id: '2', name: 'fromB' }; - await dbB.put(jsonB1); - - let errorOnA = false; - let errorOnB = false; - syncA.on('error', () => { - errorOnA = true; - }); - syncB.on('error', () => { - errorOnB = true; - }); - - const spySync = sandbox.spy(syncWorker_module, 'syncWorker'); - - // Either dbA or dbB will get UnfetchedCommitExistsError - // and retry automatically. - const [resultA, resultB] = await Promise.all([syncA.trySync(), syncB.trySync()]); - - const nextResultA = await syncA.trySync(); - const nextResultB = await syncB.trySync(); - - if (errorOnA) { - expect(resultA.action).toBe('merge and push'); - expect(nextResultA.action).toBe('nop'); - expect(resultB.action).toBe('push'); - expect(nextResultB.action).toBe('fast-forward merge'); - } - else { - expect(resultA.action).toBe('push'); - expect(nextResultA.action).toBe('fast-forward merge'); - expect(resultB.action).toBe('merge and push'); - expect(nextResultB.action).toBe('nop'); - } - expect(spySync.callCount).toBe(5); - - await destroyDBs([dbA, dbB]); - }); - - it('does not retry trySync() in init() after error except connection errors and resolvable errors', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'both', - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = await dbA.sync(options); - - const stubSync = sandbox.stub(syncWorker_module, 'syncWorker'); - stubSync.rejects(); - - await expect(sync.init(dbA.repository()!)).rejects.toThrowError(); - - expect(stubSync.callCount).toBe(1); - - await destroyDBs([dbA]); - }); - - it('does not occur when retry option is 0', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'push', - retryInterval: 0, - retry: 0, - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = new Sync(dbA, options); - const stubNet = sandbox.stub(sync, 'canNetworkConnection'); - stubNet.resolves(false); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.rejects(); - - await expect(sync.init(dbA.repository()!)).rejects.toThrowError(); - - expect(stubPush.callCount).toBe(1); - - await destroyDBs([dbA]); - }); - - it('retries every retry interval', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - await dbA.open(); - - const interval = 100000; - const retryInterval = 5000; - - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'push', - interval, - retryInterval, - retry: 2, - connection: { type: 'github', personalAccessToken: token }, - }; - - const sync = new Sync(dbA, options); - const stubNet = sandbox.stub(sync, 'canNetworkConnection'); - stubNet.resolves(false); - - const stubPush = sandbox.stub(pushWorker_module, 'pushWorker'); - stubPush.rejects(); - - sync.init(dbA.repository()!).catch(() => {}); - - await sleep(retryInterval - 500); - expect(stubPush.callCount).toBe(1); - await sleep(retryInterval); - expect(stubPush.callCount).toBe(2); - await sleep(retryInterval); - expect(stubPush.callCount).toBe(3); - await sleep(retryInterval); - - await destroyDBs([dbA]); - }); - }); - }); - - /** - * Initialize synchronization by sync() with remoteURL - * Initialize means creating local and remote repositories by using a remoteUrl - */ - describe('initialized by sync():', () => { - it('throws RemoteAlreadyRegisteredError when sync() the same url twice.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - - await dbA.open(); - - const options: RemoteOptions = { - remoteUrl: remoteURL, - connection: { type: 'github', personalAccessToken: token }, - }; - const syncA = await dbA.sync(options); - await expect(dbA.sync(options)).rejects.toThrowError( - Err.RemoteAlreadyRegisteredError - ); - dbA.destroy(); - }); - - it('After dbA#sync() created remote repository, dbB#open() clones it.', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - - await dbA.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - syncDirection: 'both', - connection: { type: 'github', personalAccessToken: token }, - }; - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - - const syncA = await dbA.sync(options); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - await dbB.sync(options); - await expect(dbB.get(jsonA1._id)).resolves.toMatchObject(jsonA1); - - await destroyDBs([dbA, dbB]); - }); - - it('After dbA#sync() created remote repository, dbB#open() clones it, close(), open() again with no remote, following sync().', async () => { - const remoteURL = remoteURLBase + serialId(); - const dbNameA = serialId(); - - const dbA: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameA, - localDir: localDir, - }); - - await dbA.open(); - const options: RemoteOptions = { - remoteUrl: remoteURL, - live: true, - interval: MINIMUM_SYNC_INTERVAL, - syncDirection: 'both', - connection: { type: 'github', personalAccessToken: token }, - }; - const jsonA1 = { _id: '1', name: 'fromA' }; - await dbA.put(jsonA1); - - const syncA = await dbA.sync(options); - - const dbNameB = serialId(); - const dbB: GitDocumentDB = new GitDocumentDB({ - dbName: dbNameB, - localDir: localDir, - }); - await dbB.open(); - await dbB.sync(options); - await dbB.close(); - - await dbB.open(); - const jsonB1 = { _id: '1', name: 'fromB' }; - await dbB.put(jsonB1); - - await dbB.sync(options); - await expect(dbB.get(jsonB1._id)).resolves.toMatchObject(jsonB1); - - // Wait next sync() - const count = dbA.taskQueue.currentStatistics().sync; - while (dbA.taskQueue.currentStatistics().sync === count) { - // eslint-disable-next-line no-await-in-loop - await sleep(500); - } - await expect(dbA.get(jsonA1._id)).resolves.toMatchObject(jsonB1); - - await destroyDBs([dbA, dbB]); - }); - }); - - it.skip('Multiple Sync object'); -}); diff --git a/test_plugin/remote_nodegit/3way_merge.test.ts b/test_plugin/remote_nodegit/3way_merge.test.ts new file mode 100644 index 00000000..9b8165ec --- /dev/null +++ b/test_plugin/remote_nodegit/3way_merge.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test tryPush + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncThreeWayMergeBase } from '../../test/remote_base/3way_merge'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_3way_merge_nodegit__'; +const localDir = `./test_plugin/database_3way_merge_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncThreeWayMergeBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/3way_merge_ot.test.ts b/test_plugin/remote_nodegit/3way_merge_ot.test.ts new file mode 100644 index 00000000..dbfd754e --- /dev/null +++ b/test_plugin/remote_nodegit/3way_merge_ot.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test trySync + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { threeWayMergeOtBase } from '../../test/remote_base/3way_merge_ot'; + +const reposPrefix = 'test_3way_merge_ot_nodegit__'; +const localDir = `./test_plugin/database_3way_merge_ot_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', threeWayMergeOtBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/combine.test.ts b/test_plugin/remote_nodegit/combine.test.ts new file mode 100644 index 00000000..94169f42 --- /dev/null +++ b/test_plugin/remote_nodegit/combine.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test combine databases + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncCombineBase } from '../../test/remote_base/combine'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_combine_nodegit__'; +const localDir = `./test_plugin/database_combine_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncCombineBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/network_git_documentdb.test.ts b/test_plugin/remote_nodegit/network_git_documentdb.test.ts new file mode 100644 index 00000000..75040780 --- /dev/null +++ b/test_plugin/remote_nodegit/network_git_documentdb.test.ts @@ -0,0 +1,64 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for GitDocumentDB class + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { networkGitDocumentDBBase } from '../../test/remote_base/network_git_documentdb'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_network_git_documentdb_nodegit__'; +const localDir = `./test_plugin/database_network_git_documentdb_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe( + 'NodeGit', + networkGitDocumentDBBase(connection, remoteURLBase, reposPrefix, localDir) +); diff --git a/test_plugin/remote_nodegit/network_history.test.ts b/test_plugin/remote_nodegit/network_history.test.ts new file mode 100644 index 00000000..c1001286 --- /dev/null +++ b/test_plugin/remote_nodegit/network_history.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for history + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { networkHistoryBase } from '../../test/remote_base/network_history'; + +const reposPrefix = 'test_network_history_nodegit__'; +const localDir = `./test_plugin/database_network_history_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', networkHistoryBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/network_task_queue.test.ts b/test_plugin/remote_nodegit/network_task_queue.test.ts new file mode 100644 index 00000000..a180f70f --- /dev/null +++ b/test_plugin/remote_nodegit/network_task_queue.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Network test for TaskQueue + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { networkTaskQueueBase } from '../../test/remote_base/network_task_queue'; + +const reposPrefix = 'test_network_task_queue_nodegit__'; +const localDir = `./test_plugin/database_network_task_queue_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', networkTaskQueueBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/on_sync_event.test.ts b/test_plugin/remote_nodegit/on_sync_event.test.ts new file mode 100644 index 00000000..1473b972 --- /dev/null +++ b/test_plugin/remote_nodegit/on_sync_event.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test trySync + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { onSyncEventBase } from '../../test/remote_base/on_sync_event'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_on_sync_event_nodegit__'; +const localDir = `./test_plugin/database_on_sync_event_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', onSyncEventBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/sync.test.ts b/test_plugin/remote_nodegit/sync.test.ts new file mode 100644 index 00000000..1e8e1b3f --- /dev/null +++ b/test_plugin/remote_nodegit/sync.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +import path from 'path'; +import fs from 'fs-extra'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; +import { syncBase } from '../../test/remote_base/sync'; + +const reposPrefix = 'test_sync_constructor_nodegit__'; +const localDir = `./test_plugin/database_sync_constructor_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncBase(connection, remoteURLBase, reposPrefix, localDir, token)); diff --git a/test_plugin/remote_nodegit/sync_clone.test.ts b/test_plugin/remote_nodegit/sync_clone.test.ts new file mode 100644 index 00000000..98e93ad2 --- /dev/null +++ b/test_plugin/remote_nodegit/sync_clone.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test tryPush + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncCloneBase } from '../../test/remote_base/sync_clone'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_sync_clone_nodegit___'; +const localDir = `./test_plugin/database_sync_clone_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncCloneBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/sync_events.test.ts b/test_plugin/remote_nodegit/sync_events.test.ts new file mode 100644 index 00000000..ece785c4 --- /dev/null +++ b/test_plugin/remote_nodegit/sync_events.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test Sync Events + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncEventsBase } from '../../test/remote_base/sync_events'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_sync_events_nodegit___'; +const localDir = `./test_plugin/database_sync_events_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncEventsBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/sync_live.test.ts b/test_plugin/remote_nodegit/sync_live.test.ts new file mode 100644 index 00000000..3fbb3032 --- /dev/null +++ b/test_plugin/remote_nodegit/sync_live.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test Sync live + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncLiveBase } from '../../test/remote_base/sync_live'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_sync_live_nodegit___'; +const localDir = `./test_plugin/database_sync_live_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncLiveBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/sync_trypush.test.ts b/test_plugin/remote_nodegit/sync_trypush.test.ts new file mode 100644 index 00000000..cb6f3ab7 --- /dev/null +++ b/test_plugin/remote_nodegit/sync_trypush.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test tryPush + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncTryPushBase } from '../../test/remote_base/sync_trypush'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_sync_trypush_nodegit___'; +const localDir = `./test_plugin/database_sync_trypush_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncTryPushBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/remote_nodegit/sync_trysync.test.ts b/test_plugin/remote_nodegit/sync_trysync.test.ts new file mode 100644 index 00000000..73e60eac --- /dev/null +++ b/test_plugin/remote_nodegit/sync_trysync.test.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +/** + * GitDocumentDB + * Copyright (c) Hidekazu Kubota + * + * This source code is licensed under the Mozilla Public License Version 2.0 + * found in the LICENSE file in the root directory of this source tree. + */ + +/** + * Test trySync + * by using GitHub Personal Access Token + * These tests create a new repository on GitHub if not exists. + */ +import path from 'path'; +import fs from 'fs-extra'; +import { syncTrySyncBase } from '../../test/remote_base/sync_trysync'; +import { ConnectionSettingsGitHub } from '../../src/types'; +import { GitDocumentDB } from '../../src/git_documentdb'; + +const reposPrefix = 'test_sync_trysync_nodegit___'; +const localDir = `./test_plugin/database_sync_trysync_nodegit`; + +beforeEach(function () { + // @ts-ignore + console.log(`... ${this.currentTest.fullTitle()}`); +}); + +before(() => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + GitDocumentDB.plugin(require('git-documentdb-plugin-remote-nodegit')); + + fs.removeSync(path.resolve(localDir)); +}); + +after(() => { + fs.removeSync(path.resolve(localDir)); +}); + +// This test needs environment variables: +// - GITDDB_GITHUB_USER_URL: URL of your GitHub account +// e.g.) https://github.com/foo/ +// - GITDDB_PERSONAL_ACCESS_TOKEN: A personal access token of your GitHub account +const maybe = + process.env.GITDDB_GITHUB_USER_URL && process.env.GITDDB_PERSONAL_ACCESS_TOKEN + ? describe + : describe.skip; + +const remoteURLBase = process.env.GITDDB_GITHUB_USER_URL?.endsWith('/') + ? process.env.GITDDB_GITHUB_USER_URL + : process.env.GITDDB_GITHUB_USER_URL + '/'; + +const token = process.env.GITDDB_PERSONAL_ACCESS_TOKEN!; + +const connection: ConnectionSettingsGitHub = { + type: 'github', + personalAccessToken: token, + engine: 'nodegit', +}; + +maybe('NodeGit', syncTrySyncBase(connection, remoteURLBase, reposPrefix, localDir)); diff --git a/test_plugin/tsconfig.json b/test_plugin/tsconfig.json new file mode 100644 index 00000000..607d44fc --- /dev/null +++ b/test_plugin/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig-base", + "include": [ + "**/*", + ], +} \ No newline at end of file diff --git a/tsconfig-base.json b/tsconfig-base.json index e12b55c0..79091dd7 100644 --- a/tsconfig-base.json +++ b/tsconfig-base.json @@ -15,15 +15,11 @@ "baseUrl": ".", "outDir": "dist", "paths": { - "@sosuisen/nodegit": [ - "types/sosuisen__nodegit" - ], "*": [ "node_modules/*" ], }, "typeRoots": [ - "types", "node_modules/@types" ], }, diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index a13bec62..5a24448a 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -3,7 +3,8 @@ "include": [ "src/**/*", "test/**/*", - "test_intg/**/*", + "test_plugin/**/*", + "benchmark/**/*", "webpack.*" ], } \ No newline at end of file diff --git a/types/sosuisen__nodegit/LICENSE b/types/sosuisen__nodegit/LICENSE deleted file mode 100644 index 9e841e7a..00000000 --- a/types/sosuisen__nodegit/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - MIT License - - Copyright (c) Microsoft Corporation. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE diff --git a/types/sosuisen__nodegit/README.md b/types/sosuisen__nodegit/README.md deleted file mode 100644 index 7bf35d48..00000000 --- a/types/sosuisen__nodegit/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Installation -> `npm install --save @types/nodegit` - -# Summary -This package contains type definitions for nodegit (https://github.com/nodegit/nodegit). - -# Details -Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nodegit. - -### Additional Details - * Last updated: Mon, 26 Oct 2020 20:58:07 GMT - * Dependencies: [@types/node](https://npmjs.com/package/@types/node) - * Global values: none - -# Credits -These definitions were written by [Dolan Miu](https://github.com/dolanmiu), [Tobias Nießen](https://github.com/tniessen), [Pierre Vigier](https://github.com/pvigier), [Jibril Saffi](https://github.com/IGI-111), [Benjamin Schuster-Boeckler](https://github.com/DaGaMs), and [Julien Chaumond](https://github.com/julien-c). diff --git a/types/sosuisen__nodegit/annotated-commit.d.ts b/types/sosuisen__nodegit/annotated-commit.d.ts deleted file mode 100644 index c6d910b5..00000000 --- a/types/sosuisen__nodegit/annotated-commit.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; -import { Reference } from './reference'; - -export class AnnotatedCommit { - /** - * @param repo - repository that contains the given commit - * @param branchName - name of the (remote) branch - * @param remoteUrl - url of the remote - * @param id - the commit object id of the remote branch - */ - static fromFetchhead(repo: Repository, branchName: string, remoteUrl: string, id: Oid): Promise; - static fromRef(repo: Repository, ref: Reference): Promise; - static fromRevspec(repo: Repository, revspec: string): Promise; - static lookup(repo: Repository, id: Oid): Promise; - - free(): void; - id(): Oid; -} diff --git a/types/sosuisen__nodegit/apply-options.d.ts b/types/sosuisen__nodegit/apply-options.d.ts deleted file mode 100644 index 730722cb..00000000 --- a/types/sosuisen__nodegit/apply-options.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ConvenientHunk } from './convenient-hunk'; -import { DiffDelta } from './diff-delta'; - -export class ApplyOptions { - deltaCb?: (delta: DiffDelta, payload: any) => number; - hunkCb?: (hunk: ConvenientHunk, payload: any) => number; - version?: number; -} diff --git a/types/sosuisen__nodegit/apply.d.ts b/types/sosuisen__nodegit/apply.d.ts deleted file mode 100644 index 8b94a4ee..00000000 --- a/types/sosuisen__nodegit/apply.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ApplyOptions } from './apply-options'; -import { Diff } from './diff'; -import { Index } from './index_'; -import { Repository } from './repository'; -import { Tree } from './tree'; - -export namespace Apply { - const enum FLAGS { - CHECK = 1 - } - - const enum LOCATION { - WORKDIR = 0, - INDEX = 1, - BOTH = 2 - } -} - -export class Apply { - static apply(repo: Repository, diff: Diff, location: Apply.LOCATION, options: ApplyOptions): Promise; - static toTree(repo: Repository, preimage: Tree, diff: Diff, options: ApplyOptions): Promise; -} diff --git a/types/sosuisen__nodegit/attr.d.ts b/types/sosuisen__nodegit/attr.d.ts deleted file mode 100644 index a9c51ae8..00000000 --- a/types/sosuisen__nodegit/attr.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Repository } from './repository'; - -export namespace Attr { - const enum STATES { - UNSPECIFIED_T = 0, - TRUE_T = 1, - FALSE_T = 2, - VALUE_T = 3 - } -} - -export class Attr { - static addMacro(repo: Repository, name: string, values: string): number; - static cacheFlush(repo: Repository): void; - /** - * @param repo - The repository containing the path. - * @param flags - A combination of GIT_ATTR_CHECK... flags. - * @param path - The path to check for attributes. Relative paths are interpreted relative to the repo root. - * The file does not have to exist, but if it does not, then it will be treated as a plain file (not a directory). - * @param name - The name of the attribute to look up. - * @returns - Output of the value of the attribute. Use the GIT_ATTR_... - */ - static get(repo: Repository, flags: number, path: string, name: string): Promise; - /** - * @param repo - The repository containing the path. - * @param flags - A combination of GIT_ATTR_CHECK... flags. - * @param path - The path to check for attributes. Relative paths are interpreted relative to the repo root. - * The file does not have to exist, but if it does not, then it will be treated as a plain file (not a directory). - * @param numAttr - The number of attributes being looked up - * @param names - An array of num_attr strings containing attribute names. - */ - static getMany(repo: Repository, flags: number, path: string, numAttr: number, names: string): any[]; - /** - * @param attr - The attribute - * @returns - the value type for the attribute - */ - static value(attr: string): number; -} diff --git a/types/sosuisen__nodegit/blame-hunk.d.ts b/types/sosuisen__nodegit/blame-hunk.d.ts deleted file mode 100644 index 385c0603..00000000 --- a/types/sosuisen__nodegit/blame-hunk.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Oid } from './oid'; -import { Signature } from './signature'; - -export class BlameHunk { - linesInHunk(): number; - finalCommitId(): Oid; - finalStartLineNumber(): number; - finalSignature(): Signature; - origCommitId(): Oid; - origPath(): string; - origStartLineNumber(): number; - origSignature(): Signature; -} diff --git a/types/sosuisen__nodegit/blame-options.d.ts b/types/sosuisen__nodegit/blame-options.d.ts deleted file mode 100644 index 1fdc6f62..00000000 --- a/types/sosuisen__nodegit/blame-options.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Oid } from './oid'; - -export class BlameOptions { - version?: number; - flags?: number; - minMatchCharacters?: number; - newestCommit?: Oid; - oldestCommit?: Oid; - minLine?: number; - maxLine?: number; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/blame.d.ts b/types/sosuisen__nodegit/blame.d.ts deleted file mode 100644 index fd1289f5..00000000 --- a/types/sosuisen__nodegit/blame.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Repository } from './repository'; -import { BlameOptions } from './blame-options'; -import { BlameHunk } from './blame-hunk'; - -export namespace Blame { - const enum FLAG { - NORMAL = 0, - TRACK_COPIES_SAME_FILE = 1, - TRACK_COPIES_SAME_COMMIT_MOVES = 2, - TRACK_COPIES_SAME_COMMIT_COPIES = 4, - TRACK_COPIES_ANY_COMMIT_COPIES = 8, - FIRST_PARENT = 16 - } -} - -export class Blame { - /** - * Retrieve the blame of a file - * - * @param repo - Repository that contains the file - * @param path - to the file to get the blame of - * @param [options] - Options for the blame - */ - static file(repo: Repository, path: string, options?: BlameOptions): Promise; - /** - * @param opts - The git_blame_options struct to initialize - * @param version - Version of struct; pass GIT_BLAME_OPTIONS_VERSION - */ - static initOptions(opts: BlameOptions, version: number): number; - - buffer(buffer: string, bufferLen: number): Promise; - - free(): void; - /** - * @returns - the hunk at the given index, or NULL on error - */ - getHunkByIndex(index: number): BlameHunk; - /** - * @returns - the hunk that contains the given line, or NULL on error - */ - getHunkByLine(lineNo: number): BlameHunk; - - getHunkCount(): number; -} diff --git a/types/sosuisen__nodegit/blob.d.ts b/types/sosuisen__nodegit/blob.d.ts deleted file mode 100644 index 1b8b09e3..00000000 --- a/types/sosuisen__nodegit/blob.d.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { WriteStream } from 'fs'; -import { Wrapper } from "./wrapper"; -import { Repository } from './repository'; -import { Oid } from './oid'; - -export class Blob { - /** - * @param repo - repository where to blob will be written - * @param buffer - data to be written into the blob - * @param len - length of the data - * @returns - return the id of the written blob - */ - static createFromBuffer(repo: Repository, buffer: Buffer, len: number): Promise; - /** - * @param repo - repository where the blob will be written. this repository can be bare or not - * @param path - file from which the blob will be created - */ - static createFromDisk(repo: Repository, path: string): Promise; - static createFromStream(repo: Repository, hintPath: string): Promise; - /** - * @param repo - repository where the blob will be written. this repository cannot be bare - * @param relativePath - file from which the blob will be created, relative to the repository's working dir - * @returns - 0 or an error code - */ - static createFromWorkdir(repo: Repository, relativePath: string): Promise; - static filteredContent(blob: Blob, as_path: string, check_for_binary_data: number): Promise; - static lookup(repo: Repository, id: string | Oid | Blob): Promise; - static lookupPrefix(repo: Repository, id: Oid, len: number): Promise; - - free(): void; - id(): Oid; - isBinary(): number; - owner(): Repository; - rawcontent(): Wrapper; - rawsize(): number; - content(): Buffer; - toString(): string; - filemode(): number; - dup(): Promise; -} diff --git a/types/sosuisen__nodegit/branch.d.ts b/types/sosuisen__nodegit/branch.d.ts deleted file mode 100644 index 71dc35b0..00000000 --- a/types/sosuisen__nodegit/branch.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Repository } from './repository'; -import { Reference } from './reference'; -import { Commit } from './commit'; -import { AnnotatedCommit } from './annotated-commit'; - -export namespace Branch { - const enum BRANCH { - LOCAL = 1, - REMOTE = 2, - ALL = 3 - } -} - -export class Branch { - static create(repo: Repository, branchName: string, target: Commit, force: number): Promise; - static createFromAnnotated(repository: Repository, branchName: string, commit: AnnotatedCommit, force: number): Reference; - static delete(branch: Reference): number; - static isHead(branch: Reference): number; - static iteratorNew(repo: Repository, listFlags: number): Promise; - static lookup(repo: Repository, branchName: string, branchType: Branch.BRANCH): Promise; - static move(branch: Reference, newBranchName: string, force: number): Promise; - static name(ref: Reference): Promise; - static setUpstream(branch: Reference, upstreamName: string): Promise; - static upstream(branch: Reference): Promise; -} diff --git a/types/sosuisen__nodegit/buf.d.ts b/types/sosuisen__nodegit/buf.d.ts deleted file mode 100644 index 5aefac72..00000000 --- a/types/sosuisen__nodegit/buf.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -/// - -export class Buf { - containsNul(): number; - - free(): void; - grow(targetSize: number): Promise; - isBinary(): number; - set(data: Buffer, datalen: number): Promise; - ptr: string; - asize: number; - size: number; -} diff --git a/types/sosuisen__nodegit/cert-host-key.d.ts b/types/sosuisen__nodegit/cert-host-key.d.ts deleted file mode 100644 index 9932f666..00000000 --- a/types/sosuisen__nodegit/cert-host-key.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Cert } from './cert'; - -export class CertHostkey { - parent: Cert; - type: Cert.TYPE; - hashMd5: string; - hashSha1: string; -} diff --git a/types/sosuisen__nodegit/cert-x509.d.ts b/types/sosuisen__nodegit/cert-x509.d.ts deleted file mode 100644 index 44f6d5a7..00000000 --- a/types/sosuisen__nodegit/cert-x509.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Cert } from './cert'; - -export class CertX509 { - data: Buffer; - len: number; - parent: Cert; -} diff --git a/types/sosuisen__nodegit/cert.d.ts b/types/sosuisen__nodegit/cert.d.ts deleted file mode 100644 index fde86569..00000000 --- a/types/sosuisen__nodegit/cert.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -export namespace Cert { - const enum TYPE { - NONE = 0, - X509 = 1, - HOSTKEY_LIBSSH2 = 2, - STRARRAY = 3 - } - - const enum SSH { - MD5 = 1, - SHA1 = 2 - } -} - -export class Cert { - certType: Cert.TYPE; -} diff --git a/types/sosuisen__nodegit/checkout-options.d.ts b/types/sosuisen__nodegit/checkout-options.d.ts deleted file mode 100644 index 6971f59f..00000000 --- a/types/sosuisen__nodegit/checkout-options.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Strarray } from './str-array'; -import { Tree } from './tree'; -import { Index } from './index'; - -export class CheckoutOptions { - version?: number; - checkoutStrategy?: number; - disableFilters?: number; - dirMode?: number; - fileMode?: number; - fileOpenFlags?: number; - notifyFlags?: number; - notifyCb?: any; - notifyPayload?: undefined; - progressCb?: any; - progressPayload?: undefined; - paths?: Strarray | string | string[]; - baseline?: Tree; - baselineIndex?: Index; - targetDirectory?: string; - ancestorLabel?: string; - ourLabel?: string; - theirLabel?: string; - perfdataCb?: any; - perfdataPayload?: undefined; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/checkout.d.ts b/types/sosuisen__nodegit/checkout.d.ts deleted file mode 100644 index c29dd2d2..00000000 --- a/types/sosuisen__nodegit/checkout.d.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Repository } from './repository'; -import { CheckoutOptions } from './checkout-options'; -import { Reference } from './reference'; -import { Oid } from './oid'; -import { Tree } from './tree'; -import { Commit } from './commit'; -import { Index } from './index'; - -export namespace Checkout { - const enum NOTIFY { - NONE = 0, - CONFLICT = 1, - DIRTY = 2, - UPDATED = 4, - UNTRACKED = 8, - IGNORED = 16, - ALL = 65535 - } - - const enum STRATEGY { - NONE = 0, - SAFE = 1, - FORCE = 2, - RECREATE_MISSING = 4, - ALLOW_CONFLICTS = 16, - REMOVE_UNTRACKED = 32, - REMOVE_IGNORED = 64, - UPDATE_ONLY = 128, - DONT_UPDATE_INDEX = 256, - NO_REFRESH = 512, - SKIP_UNMERGED = 1024, - USE_OURS = 2048, - USE_THEIRS = 4096, - DISABLE_PATHSPEC_MATCH = 8192, - SKIP_LOCKED_DIRECTORIES = 262144, - DONT_OVERWRITE_IGNORED = 524288, - CONFLICT_STYLE_MERGE = 1048576, - CONFLICT_STYLE_DIFF3 = 2097152, - DONT_REMOVE_EXISTING = 4194304, - DONT_WRITE_INDEX = 8388608, - UPDATE_SUBMODULES = 65536, - UPDATE_SUBMODULES_IF_CHANGED = 131072 - } -} - -export class Checkout { - /** - * Patch head checkout to automatically coerce objects. - */ - static head(repo: Repository, options?: CheckoutOptions): Promise; - /** - * Patch index checkout to automatically coerce objects. - */ - static index(repo: Repository, The: Index, options?: CheckoutOptions): Promise; - - static initOptions(opts: CheckoutOptions, version: number): number; - /** - * Patch tree checkout to automatically coerce objects. - */ - static tree(repo: Repository, treeish: Oid | Tree | Commit | Reference, options?: CheckoutOptions): Promise; -} diff --git a/types/sosuisen__nodegit/cherry-pick-options.d.ts b/types/sosuisen__nodegit/cherry-pick-options.d.ts deleted file mode 100644 index cde3c0a3..00000000 --- a/types/sosuisen__nodegit/cherry-pick-options.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { MergeOptions } from './merge-options'; -import { CheckoutOptions } from './checkout-options'; - -export interface CherrypickOptions { - version?: number; - mainline?: number; - mergeOpts?: MergeOptions; - checkoutOpts?: CheckoutOptions; -} diff --git a/types/sosuisen__nodegit/cherry-pick.d.ts b/types/sosuisen__nodegit/cherry-pick.d.ts deleted file mode 100644 index 168de79e..00000000 --- a/types/sosuisen__nodegit/cherry-pick.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Repository } from './repository'; -import { Commit } from './commit'; -import { MergeOptions } from './merge-options'; -import { CherrypickOptions } from './cherry-pick-options'; - -export class Cherrypick { - /** - * Cherrypick a commit and, changing the index and working directory - */ - static cherrypick(repo: Repository, commit: Commit, options?: CherrypickOptions): Promise; - /** - * Cherrypicks the given commit against "our" commit, producing an index that reflects the result of the cherrypick. The index is not backed by a repo. - */ - static commit(repo: Repository, cherrypickCommit: Commit, ourCommit: Commit, mainline: number, mergeOptions?: MergeOptions): Promise; - static initOptions(opts: CherrypickOptions, version: number): number; -} diff --git a/types/sosuisen__nodegit/clone-options.d.ts b/types/sosuisen__nodegit/clone-options.d.ts deleted file mode 100644 index 8535b28c..00000000 --- a/types/sosuisen__nodegit/clone-options.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CheckoutOptions } from './checkout-options'; -import { FetchOptions } from './fetch-options'; - -export class CloneOptions { - version?: number; - checkoutOpts?: CheckoutOptions; - fetchOpts?: FetchOptions; - bare?: number; - local?: number; - checkoutBranch?: string; - repositoryCbPayload?: any; - remoteCbPayload?: any; -} diff --git a/types/sosuisen__nodegit/clone.d.ts b/types/sosuisen__nodegit/clone.d.ts deleted file mode 100644 index 15933d41..00000000 --- a/types/sosuisen__nodegit/clone.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Repository } from './repository'; -import { CloneOptions } from './clone-options'; - -export namespace Clone { - const enum LOCAL { - AUTO = 0, - LOCAL = 1, - NO_LOCAL = 2, - NO_LINKS = 3 - } -} - -export class Clone { - /** - * Patch repository cloning to automatically coerce objects. - */ - static clone(url: string, localPath: string, options?: CloneOptions): Promise; - - static initOptions(opts: CloneOptions, version: number): number; -} diff --git a/types/sosuisen__nodegit/commit.d.ts b/types/sosuisen__nodegit/commit.d.ts deleted file mode 100644 index 8152eb8a..00000000 --- a/types/sosuisen__nodegit/commit.d.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { EventEmitter } from 'events'; - -import { Repository } from './repository'; -import { Signature } from './signature'; -import { Oid } from './oid'; -import { Buf } from './buf'; -import { Object } from './object'; -import { Tree } from './tree'; -import { TreeEntry } from './tree-entry'; -import { Diff } from './diff'; - -export interface HistoryEventEmitter extends EventEmitter { - start(): void; -} - -export class Commit { - static create(repo: Repository, updateRef: string, author: Signature, committer: Signature, messageEncoding: string, message: string, tree: Tree, parentCount: number, parents: any[]): Oid; - static createV(id: Oid, repo: Repository, updateRef: string, author: Signature, committer: Signature, messageEncoding: string, message: string, tree: Tree, parentCount: number): number; - /** - * Retrieves the commit pointed to by the oid - * - * - */ - static lookup(repo: Repository, id: string | Oid | Commit): Promise; - static lookupPrefix(repo: Repository, id: Oid, len: number): Promise; - static createWithSignature(repo: Repository, commitContent: string, signature: string, signatureField: string): Promise; - - amend(updateRef: string, author: Signature, committer: Signature, messageEncoding: string, message: string, tree: Tree | Oid): Promise; - author(): Signature; - committer(): Signature; - - free(): void; - headerField(field: string): Promise; - id(): Oid; - message(): string; - messageEncoding(): string; - messageRaw(): string; - nthGenAncestor(n: number): Promise; - owner(): Repository; - parent(n: number): Promise; - parentId(n: number): Oid; - parentcount(): number; - rawHeader(): string; - summary(): string; - time(): number; - timeOffset(): number; - tree(treeOut: Tree): number; - treeId(): Oid; - /** - * Retrieve the SHA. - * - * - */ - sha(): string; - /** - * Retrieve the commit time as a unix timestamp. - * - * - */ - timeMs(): number; - /** - * Retrieve the commit time as a Date object. - * - * - */ - date(): Date; - /** - * Get the tree associated with this commit. - * - * - */ - getTree(): Promise; - /** - * Retrieve the entry represented by path for this commit. Path must be relative to repository root. - * - * - */ - getEntry(path: string): Promise; - /** - * Walk the history from this commit backwards. - * An EventEmitter is returned that will emit a "commit" event for each commit in the history, and one "end" - * event when the walk is completed. Don't forget to call start() on the returned EventEmitter. - * - * - */ - history(): HistoryEventEmitter; - /** - * Retrieve the commit's parents as commit objects. - * - * - */ - getParents(limit: number, callback?: Function): Promise; - /** - * Retrieve the commit's parent shas. - * - * - */ - parents(): Oid[]; - /** - * Generate an array of diff trees showing changes between this commit and its parent(s). - * - * - */ - getDiff(callback?: Function): Promise; - /** - * Generate an array of diff trees showing changes between this commit and its parent(s). - * - * - */ - getDiffWithOptions(options: Object, callback?: Function): Promise; - /** - * The sha of this commit - * - * - */ - toString(): string; - dup(): Promise; - /** - * consists of a summary - * - * - */ - body(): string; -} diff --git a/types/sosuisen__nodegit/config.d.ts b/types/sosuisen__nodegit/config.d.ts deleted file mode 100644 index 0f707efe..00000000 --- a/types/sosuisen__nodegit/config.d.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Buf } from './buf'; - -export namespace Config { - const enum LEVEL { - SYSTEM = 1, - XDG = 2, - GLOBAL = 3, - LOCAL = 4, - APP = 5, - HIGHEST_LEVEL = -1 - } - - const enum MAP { - FALSE = 0, - TRUE = 1, - INT32 = 2, - STRING = 3, - } -} - -export class ConfigEntry { - // the documentation says those are variables, - // but in reality they are functions - level(): number; - name(): number; - value(): string; -} - -export class Config { - static findGlobal(): Promise; // the docs says it's a buff but it's actually a string - static findProgramdata(): Promise; - static findSystem(): Promise; - static findXdg(): Promise; - static openDefault(): Promise; - static openOndisk(path: string): Promise; - - deleteEntry(name: string): number; - deleteMultivar(name: string, regexp: string): number; - getBool(name: string): Promise; - getEntry(name: string): Promise; - getInt32(name: string): Promise; - getInt64(name: string): Promise; - getPath(name: string): Promise; // the docs says Buf but it's actually a string - getStringBuf(name: string): Promise; - lock(transaction: any): number; - setBool(name: string, value: number): Promise; - setInt32(name: string, value: number): Promise; - setInt64(name: string, value: number): number; - setMultivar(name: string, regexp: string, value: string): Promise; - setString(name: string, value: string): Promise; - snapshot(): Promise; -} diff --git a/types/sosuisen__nodegit/convenient-hunk.d.ts b/types/sosuisen__nodegit/convenient-hunk.d.ts deleted file mode 100644 index a844fd4e..00000000 --- a/types/sosuisen__nodegit/convenient-hunk.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { DiffLine } from './diff-line'; - -export class ConvenientHunk { - /** - * Diff header string that represents the context of this hunk - * of the diff. Something like `@@ -169,14 +167,12 @@ ...` - */ - header(): string; - /** - * The length of the header - */ - headerLen(): number; - /** - * The lines in this hunk - */ - lines(): Promise; - /** - * The number of new lines in the hunk - */ - newLines(): number; - /** - * The starting offset of the first new line in the file - */ - newStart(): number; - /** - * The number of old lines in the hunk - */ - oldLines(): number; - /** - * The starting offset of the first old line in the file - */ - oldStart(): number; - /** - * Number of lines in this hunk - */ - size(): number; -} diff --git a/types/sosuisen__nodegit/convenient-patch.d.ts b/types/sosuisen__nodegit/convenient-patch.d.ts deleted file mode 100644 index 05fa0def..00000000 --- a/types/sosuisen__nodegit/convenient-patch.d.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ConvenientHunk } from './convenient-hunk'; -import { DiffFile } from './diff-file'; - -export class ConvenientPatch { - /** - * Old attributes of the file - */ - oldFile(): DiffFile; - /** - * New attributes of the file - */ - newFile(): DiffFile; - /** - * The number of hunks in this patch - */ - size(): number; - /** - * The hunks in this patch - */ - hunks(): Promise; - /** - * The status of this patch (unmodified, added, deleted) - */ - status(): number; - /** - * The line statistics of this patch (#contexts, #added, #deleted) - */ - lineStats(): any; - /** - * Is this an unmodified patch? - */ - isUnmodified(): boolean; - /** - * Is this an added patch? - */ - isAdded(): boolean; - /** - * Is this a deleted patch? - */ - isDeleted(): boolean; - /** - * Is this an modified patch - */ - isModified(): boolean; - /** - * Is this a renamed patch? - */ - isRenamed(): boolean; - /** - * Is this a copied patch? - */ - isCopied(): boolean; - /** - * Is this an ignored patch? - */ - isIgnored(): boolean; - /** - * Is this an untracked patch? - */ - isUntracked(): boolean; - /** - * Is this a type change? - */ - isTypeChange(): boolean; - /** - * Is this an undreadable patch? - */ - isUnreadable(): boolean; - /** - * Is this a conflicted patch? - */ - isConflicted(): boolean; -} diff --git a/types/sosuisen__nodegit/cred-user-pass-payload.d.ts b/types/sosuisen__nodegit/cred-user-pass-payload.d.ts deleted file mode 100644 index 95beeb9f..00000000 --- a/types/sosuisen__nodegit/cred-user-pass-payload.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export class CredUserpassPayload { - username: string; - password: string; -} diff --git a/types/sosuisen__nodegit/cred-username.d.ts b/types/sosuisen__nodegit/cred-username.d.ts deleted file mode 100644 index d7b619eb..00000000 --- a/types/sosuisen__nodegit/cred-username.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Cred } from './cred'; - -export class CredUsername { - parent: Cred; - username: string; -} diff --git a/types/sosuisen__nodegit/cred.d.ts b/types/sosuisen__nodegit/cred.d.ts deleted file mode 100644 index 160f62f9..00000000 --- a/types/sosuisen__nodegit/cred.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -export namespace Cred { - const enum TYPE { - USERPASS_PLAINTEXT = 1, - SSH_KEY = 2, - SSH_CUSTOM = 4, - DEFAULT = 8, - SSH_INTERACTIVE = 16, - USERNAME = 32, - SSH_MEMORY = 64 - } -} - -export class Cred { - static defaultNew(): Cred; - static sshKeyFromAgent(username: string): Cred; - static sshKeyMemoryNew(username: string, publicKey: string, privateKey: string, passphrase: string): Promise; - static sshKeyNew(username: string, publicKey: string, privateKey: string, passphrase: string): Cred; - static usernameNew(username: string): Promise; - static userpassPlaintextNew(username: string, password: string): Cred; - - hasUsername(): number; - - free(): void; -} diff --git a/types/sosuisen__nodegit/cvar-map.d.ts b/types/sosuisen__nodegit/cvar-map.d.ts deleted file mode 100644 index f7c4b227..00000000 --- a/types/sosuisen__nodegit/cvar-map.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class CvarMap { - cvarType: number; - strMatch: string; - mapValue: number; -} diff --git a/types/sosuisen__nodegit/describe-format-options.d.ts b/types/sosuisen__nodegit/describe-format-options.d.ts deleted file mode 100644 index b4213f0d..00000000 --- a/types/sosuisen__nodegit/describe-format-options.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class DescribeFormatOptions { - version?: number; - abbreviatedSize?: number; - alwaysUseLongFormat?: number; - dirtySuffix?: string; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/describe-options.d.ts b/types/sosuisen__nodegit/describe-options.d.ts deleted file mode 100644 index 2934006a..00000000 --- a/types/sosuisen__nodegit/describe-options.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class DescribeOptions { - version?: number; - maxCandidatesTags?: number; - describeStrategy?: number; - pattern?: string; - onlyFollowFirstParent?: number; - showCommitOidAsFallback?: number; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/diff-binary-file.d.ts b/types/sosuisen__nodegit/diff-binary-file.d.ts deleted file mode 100644 index 362e1a63..00000000 --- a/types/sosuisen__nodegit/diff-binary-file.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Object } from './object'; - -export class DiffBinaryFile { - type: Object.TYPE; - data: string; - datalen: number; - inflatedlen: number; -} diff --git a/types/sosuisen__nodegit/diff-binary.d.ts b/types/sosuisen__nodegit/diff-binary.d.ts deleted file mode 100644 index d5f7c6fd..00000000 --- a/types/sosuisen__nodegit/diff-binary.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { DiffBinaryFile } from './diff-binary-file'; - -export namespace DiffBinary { - const enum DIFF_BINARY { - NONE = 0, - LITERAL = 1, - DELTA = 2 - } -} - -export class DiffBinary { - oldFile: DiffBinaryFile; - newFile: DiffBinaryFile; - containsData: DiffBinary.DIFF_BINARY; -} diff --git a/types/sosuisen__nodegit/diff-delta.d.ts b/types/sosuisen__nodegit/diff-delta.d.ts deleted file mode 100644 index 2afda666..00000000 --- a/types/sosuisen__nodegit/diff-delta.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { DiffFile } from './diff-file'; - -export class DiffDelta { - status: () => number; - flags: () => number; - similarity: () => number; - nfiles: () => number; - oldFile: () => DiffFile; - newFile: () => DiffFile; -} diff --git a/types/sosuisen__nodegit/diff-file.d.ts b/types/sosuisen__nodegit/diff-file.d.ts deleted file mode 100644 index 9f418ccd..00000000 --- a/types/sosuisen__nodegit/diff-file.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Oid } from './oid'; - -export class DiffFile { - /** - * Returns the file's flags - */ - flags(): number; - /** - * Returns the file's Oid - */ - id(): Oid; - /** - * Returns the file's mode - */ - mode(): number; - /** - * Returns the file's path - */ - path(): string; - /** - * Returns the file's size - */ - size(): number; -} diff --git a/types/sosuisen__nodegit/diff-line.d.ts b/types/sosuisen__nodegit/diff-line.d.ts deleted file mode 100644 index 7d1c0713..00000000 --- a/types/sosuisen__nodegit/diff-line.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -export class DiffLine { - /** - * The relevant line - * - * - */ - content(): string; - /** - * The non utf8 translated text - * - * - */ - rawContent(): string; - origin(): number; - oldLineno(): number; - newLineno(): number; - numLines(): number; - contentLen(): number; - contentOffset(): number; -} diff --git a/types/sosuisen__nodegit/diff-options.d.ts b/types/sosuisen__nodegit/diff-options.d.ts deleted file mode 100644 index 3925f5c7..00000000 --- a/types/sosuisen__nodegit/diff-options.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Strarray } from './str-array'; - -export interface DiffOptions { - version?: number; - flags?: number; - ignoreSubmodules?: number; - pathspec?: Strarray | string | string[]; - notifyCb?: Function; - contextLines?: number; - interhunkLines?: number; - idAbbrev?: number; - maxSize?: number; - oldPrefix?: string; - newPrefix?: string; - payload?: any; - progressCb?: any; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/diff-perf-data.d.ts b/types/sosuisen__nodegit/diff-perf-data.d.ts deleted file mode 100644 index 5dfca096..00000000 --- a/types/sosuisen__nodegit/diff-perf-data.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class DiffPerfdata { - version: number; - statCalls: number; - oidCalculations: number; -} diff --git a/types/sosuisen__nodegit/diff-stats.d.ts b/types/sosuisen__nodegit/diff-stats.d.ts deleted file mode 100644 index 01a5a3c8..00000000 --- a/types/sosuisen__nodegit/diff-stats.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Buf } from './buf'; - -export class DiffStats { - /** - * @returns - total number of deletions in the diff - */ - deletions(): Number; - - /** - * @returns - total number of files changed in the diff - */ - filesChanged(): Number; - - /** - * @returns - total number of insertions in the diff - */ - insertions(): Number; - - /** - * @param format - Formatting option. - * @param width - Target width for output (only affects GIT_DIFF_STATS_FULL) - * @returns - buffer to store the formatted diff statistics in. - */ - toBuf(format: Number, width: Number): Promise; -} diff --git a/types/sosuisen__nodegit/diff.d.ts b/types/sosuisen__nodegit/diff.d.ts deleted file mode 100644 index e62f59d4..00000000 --- a/types/sosuisen__nodegit/diff.d.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { Blob } from './blob'; -import { Repository } from './repository'; -import { Tree } from './tree'; -import { Strarray } from './str-array'; -import { Index } from './index_'; -import { DiffDelta } from './diff-delta'; -import { DiffPerfdata } from './diff-perf-data'; -import { DiffOptions } from './diff-options'; -import { Buf } from './buf'; -import { ConvenientPatch } from './convenient-patch'; -import { DiffStats } from './diff-stats'; - -export interface DiffFindOptions { - version?: number; - flags?: number; - renameThreshold?: number; - renameFromRewriteThreshold?: number; - copyThreshold?: number; - breakRewriteThreshold?: number; - renameLimit?: number; -} - -export namespace Diff { - const enum DELTA { - UNMODIFIED = 0, - ADDED = 1, - DELETED = 2, - MODIFIED = 3, - RENAMED = 4, - COPIED = 5, - IGNORED = 6, - UNTRACKED = 7, - TYPECHANGE = 8, - UNREADABLE = 9, - CONFLICTED = 10, - } - - const enum FIND { - BY_CONFIG = 0, - RENAMES = 1, - RENAMES_FROM_REWRITES = 2, - COPIES = 4, - COPIES_FROM_UNMODIFIED = 8, - REWRITES = 16, - BREAK_REWRITES = 32, - AND_BREAK_REWRITES = 48, - FOR_UNTRACKED = 64, - ALL = 255, - IGNORE_LEADING_WHITESPACE = 0, - IGNORE_WHITESPACE = 4096, - DONT_IGNORE_WHITESPACE = 8192, - EXACT_MATCH_ONLY = 16384, - BREAK_REWRITES_FOR_RENAMES_ONLY = 32768, - REMOVE_UNMODIFIED = 65536, - } - - const enum FLAG { - BINARY = 1, - NOT_BINARY = 2, - VALID_ID = 4, - EXISTS = 8, - } - - const enum FORMAT { - PATCH = 1, - PATCH_HEADER = 2, - RAW = 3, - NAME_ONLY = 4, - NAME_STATUS = 5, - } - - const enum FORMAT_EMAIL_FLAGS { - FORMAT_EMAIL_NONE = 0, - FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER = 1, - } - - const enum LINE { - CONTEXT = 32, - ADDITION = 43, - DELETION = 45, - CONTEXT_EOFNL = 61, - ADD_EOFNL = 62, - DEL_EOFNL = 60, - FILE_HDR = 70, - HUNK_HDR = 72, - BINARY = 66, - } - - const enum OPTION { - NORMAL = 0, - REVERSE = 1, - INCLUDE_IGNORED = 2, - RECURSE_IGNORED_DIRS = 4, - INCLUDE_UNTRACKED = 8, - RECURSE_UNTRACKED_DIRS = 16, - INCLUDE_UNMODIFIED = 32, - INCLUDE_TYPECHANGE = 64, - INCLUDE_TYPECHANGE_TREES = 128, - IGNORE_FILEMODE = 256, - IGNORE_SUBMODULES = 512, - IGNORE_CASE = 1024, - INCLUDE_CASECHANGE = 2048, - DISABLE_PATHSPEC_MATCH = 4096, - SKIP_BINARY_CHECK = 8192, - ENABLE_FAST_UNTRACKED_DIRS = 16384, - UPDATE_INDEX = 32768, - INCLUDE_UNREADABLE = 65536, - INCLUDE_UNREADABLE_AS_UNTRACKED = 131072, - FORCE_TEXT = 1048576, - FORCE_BINARY = 2097152, - IGNORE_WHITESPACE = 4194304, - IGNORE_WHITESPACE_CHANGE = 8388608, - IGNORE_WHITESPACE_EOL = 16777216, - SHOW_UNTRACKED_CONTENT = 33554432, - SHOW_UNMODIFIED = 67108864, - PATIENCE = 268435456, - MINIMAL = 536870912, - SHOW_BINARY = 1073741824, - } - - const enum STATS_FORMAT { - STATS_NONE = 0, - STATS_FULL = 1, - STATS_SHORT = 2, - STATS_NUMBER = 4, - STATS_INCLUDE_SUMMARY = 8, - } -} - -export class Diff { - /** - * Directly run a diff between a blob and a buffer. - * - * - */ - static blobToBuffer( - oldBlob?: Blob, - oldAsPath?: string, - buffer?: string, - bufferAsPath?: string, - opts?: DiffOptions, - fileCb?: Function, - binaryCb?: Function, - hunkCb?: Function, - lineCb?: Function, - ): Promise; - static fromBuffer(content: string, contentLen: number): Promise; - static indexToWorkdir(repo: Repository, index?: Index, opts?: DiffOptions): Promise; - static indexToIndex(repo: Repository, oldIndex: Index, newIndex: Index, opts?: DiffOptions): Promise; - static treeToIndex(repo: Repository, oldTree?: Tree, index?: Index, opts?: DiffOptions): Promise; - static treeToTree(repo: Repository, oldTree?: Tree, new_tree?: Tree, opts?: DiffOptions): Promise; - static treeToWorkdir(repo: Repository, oldTree?: Tree, opts?: DiffOptions): Promise; - static treeToWorkdirWithIndex(repo: Repository, oldTree?: Tree, opts?: DiffOptions): Promise; - - findSimilar(options?: DiffFindOptions): Promise; - getDelta(idx: number): DiffDelta; - getPerfdata(): Promise; - numDeltas(): number; - /** - * Retrieve patches in this difflist - * - * - */ - patches(): Promise; - merge(from: Diff): Promise; - toBuf(format: Diff.FORMAT): Promise; - - /** - * @returns - Structure containg the diff statistics. - */ - getStats(): Promise; -} diff --git a/types/sosuisen__nodegit/enums.d.ts b/types/sosuisen__nodegit/enums.d.ts deleted file mode 100644 index 4fb44850..00000000 --- a/types/sosuisen__nodegit/enums.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -export namespace Enums { - const enum CVAR { - FALSE = 0, - TRUE = 1, - INT32 = 2, - string = 3 - } - - const enum DIRECTION { - FETCH = 0, - PUSH = 1 - } - - const enum FEATURE { - THREADS = 1, - HTTPS = 2, - SSH = 4 - } - - const enum IDXENTRY_EXTENDED_FLAG { - IDXENTRY_INTENT_TO_ADD = 8192, - IDXENTRY_SKIP_WORKTREE = 16384, - IDXENTRY_EXTENDED2 = 32768, - S = 24576, - IDXENTRY_UPDATE = 1, - IDXENTRY_REMOVE = 2, - IDXENTRY_UPTODATE = 4, - IDXENTRY_ADDED = 8, - IDXENTRY_HASHED = 16, - IDXENTRY_UNHASHED = 32, - IDXENTRY_WT_REMOVE = 64, - IDXENTRY_CONFLICTED = 128, - IDXENTRY_UNPACKED = 256, - IDXENTRY_NEW_SKIP_WORKTREE = 512 - } - - const enum INDXENTRY_FLAG { - IDXENTRY_EXTENDED = 16384, - IDXENTRY_VALID = 32768 - } -} diff --git a/types/sosuisen__nodegit/error.d.ts b/types/sosuisen__nodegit/error.d.ts deleted file mode 100644 index c259749e..00000000 --- a/types/sosuisen__nodegit/error.d.ts +++ /dev/null @@ -1,68 +0,0 @@ -export namespace Error { - const enum ERROR { - GITERR_NONE = 0, - GITERR_NOMEMORY = 1, - GITERR_OS = 2, - GITERR_INVALID = 3, - GITERR_REFERENCE = 4, - GITERR_ZLIB = 5, - GITERR_REPOSITORY = 6, - GITERR_CONFIG = 7, - GITERR_REGEX = 8, - GITERR_ODB = 9, - GITERR_INDEX = 10, - GITERR_OBJECT = 11, - GITERR_NET = 12, - GITERR_TAG = 13, - GITERR_TREE = 14, - GITERR_INDEXER = 15, - GITERR_SSL = 16, - GITERR_SUBMODULE = 17, - GITERR_THREAD = 18, - GITERR_STASH = 19, - GITERR_CHECKOUT = 20, - GITERR_FETCHHEAD = 21, - GITERR_MERGE = 22, - GITERR_SSH = 23, - GITERR_FILTER = 24, - GITERR_REVERT = 25, - GITERR_CALLBACK = 26, - GITERR_CHERRYPICK = 27, - GITERR_DESCRIBE = 28, - GITERR_REBASE = 29, - GITERR_FILESYSTEM = 30 - } - - const enum CODE { - OK = 0, - ERROR = -1, - ENOTFOUND = -3, - EEXISTS = -4, - EAMBIGUOUS = -5, - EBUFS = -6, - EUSER = -7, - EBAREREPO = -8, - EUNBORNBRANCH = -9, - EUNMERGED = -10, - ENONFASTFORWARD = -11, - EINVALIDSPEC = -12, - ECONFLICT = -13, - ELOCKED = -14, - EMODIFIED = -15, - EAUTH = -16, - ECERTIFICATE = -17, - EAPPLIED = -18, - EPEEL = -19, - EEOF = -20, - EINVALID = -21, - EUNCOMMITTED = -22, - EDIRECTORY = -23, - PASSTHROUGH = -30, - ITEROVER = -31 - } -} - -export class Error { - message: string; - klass: number; -} diff --git a/types/sosuisen__nodegit/fetch-options.d.ts b/types/sosuisen__nodegit/fetch-options.d.ts deleted file mode 100644 index 4a418b67..00000000 --- a/types/sosuisen__nodegit/fetch-options.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { RemoteCallbacks } from './remote-callbacks'; -import { Strarray } from './str-array'; - -export class FetchOptions { - version?: number; - callbacks?: RemoteCallbacks; - prune?: number; - updateFetchhead?: number; - downloadTags?: number; - customHeaders?: Strarray | string | string[]; - proxyOpts?: any; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/fetch.d.ts b/types/sosuisen__nodegit/fetch.d.ts deleted file mode 100644 index db098058..00000000 --- a/types/sosuisen__nodegit/fetch.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { FetchOptions } from './fetch-options'; - -export namespace Fetch { - const enum PRUNE { - GIT_FETCH_PRUNE_UNSPECIFIED = 0, - GIT_FETCH_PRUNE = 1, - GIT_FETCH_NO_PRUNE = 2 - } -} - -export class Fetch { - static initOptions(opts: FetchOptions, version: number): number; -} diff --git a/types/sosuisen__nodegit/filter.d.ts b/types/sosuisen__nodegit/filter.d.ts deleted file mode 100644 index 066a5118..00000000 --- a/types/sosuisen__nodegit/filter.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { WriteStream } from 'fs'; - -import { Repository } from './repository'; -import { Blob } from './blob'; -import { Buf } from './buf'; - -export namespace Filter { - const enum FLAG { - DEFAULT = 0, - ALLOW_UNSAFE = 1 - } - - const enum MODE { - TO_WORKTREE = 0, - SMUDGE = 0, - TO_ODB = 1, - CLEAN = 1 - } -} - -export class Filter { - static listContains(filters: any, name: string): number; - static listLength(fl: any): number; - static listNew(repo: Repository, mode: number, options: number): Promise; - static listStreamBlob(filters: any, blob: Blob, target: WriteStream): number; - static listStreamData(filters: any, data: Buf, target: WriteStream): number; - static listStreamFile(filters: any, repo: Repository, path: string, target: WriteStream): number; - static unregister(name: string): number; - - lookup(name: string): Filter; - register(name: string, priority: number): number; - version: number; - attributes: string; - stream: Function; -} diff --git a/types/sosuisen__nodegit/git-err.d.ts b/types/sosuisen__nodegit/git-err.d.ts deleted file mode 100644 index 1ba84342..00000000 --- a/types/sosuisen__nodegit/git-err.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Error } from './error'; - -export class Giterr { - static errClear(): void; - static errLast(): Error; - static errSetOom(): void; - static errSetString(errorClass: number, string: string): void; -} diff --git a/types/sosuisen__nodegit/graph.d.ts b/types/sosuisen__nodegit/graph.d.ts deleted file mode 100644 index d16d7b5d..00000000 --- a/types/sosuisen__nodegit/graph.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; - -export class Graph { - static aheadBehind(repo: Repository, local: Oid, upstream: Oid): Promise; - static descendantOf(repo: Repository, commit: Oid, ancestor: Oid): Promise; -} diff --git a/types/sosuisen__nodegit/hash-sig.d.ts b/types/sosuisen__nodegit/hash-sig.d.ts deleted file mode 100644 index 229d26d7..00000000 --- a/types/sosuisen__nodegit/hash-sig.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -export namespace Hashsig { - const enum OPTION { - NORMAL = 0, - IGNORE_WHITESPACE = 1, - SMART_WHITESPACE = 2, - ALLOW_SMALL_FILES = 4 - } -} - -export class Hashsig { - static create(buf: string, buflen: number, opts: number): Promise; - static createFromFile(path: string, opts: number): Promise; - - compare(b: Hashsig): number; - - free(): void; -} diff --git a/types/sosuisen__nodegit/ignore.d.ts b/types/sosuisen__nodegit/ignore.d.ts deleted file mode 100644 index c38d84d1..00000000 --- a/types/sosuisen__nodegit/ignore.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Repository } from './repository'; - -export class Ignore { - static addRule(repo: Repository, rules: string): number; - static clearInternalRules(repo: Repository): number; - static pathIsIgnored(repo: Repository, path: string): Promise; -} diff --git a/types/sosuisen__nodegit/index-entry.d.ts b/types/sosuisen__nodegit/index-entry.d.ts deleted file mode 100644 index 978cf24b..00000000 --- a/types/sosuisen__nodegit/index-entry.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Oid } from './oid'; - -export interface IndexTime { - seconds(): number; - nanoseconds(): number; -} - -export class IndexEntry { - ctime: IndexTime; - mtime: IndexTime; - dev: number; - ino: number; - mode: number; - uid: number; - gid: number; - fileSize: number; - id: Oid; - flags: number; - flagsExtended: number; - path: string; -} diff --git a/types/sosuisen__nodegit/index.d.ts b/types/sosuisen__nodegit/index.d.ts deleted file mode 100644 index ac621d64..00000000 --- a/types/sosuisen__nodegit/index.d.ts +++ /dev/null @@ -1,116 +0,0 @@ -// Type definitions for nodegit 0.26 -// Project: https://github.com/nodegit/nodegit, http://nodegit.org -// Definitions by: Dolan Miu , -// Tobias Nießen , -// Pierre Vigier -// Jibril Saffi -// Benjamin Schuster-Boeckler -// Julien Chaumond -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - -export { AnnotatedCommit } from './annotated-commit'; -export { Apply } from './apply'; -export { ApplyOptions } from './apply-options'; -export { Attr } from './attr'; -export { BlameHunk } from './blame-hunk'; -export { BlameOptions } from './blame-options'; -export { Blame } from './blame'; -export { Blob } from './blob'; -export { Branch } from './branch'; -export { Buf } from './buf'; -export { CertHostkey } from './cert-host-key'; -export { CertX509 } from './cert-x509'; -export { Cert } from './cert'; -export { CheckoutOptions } from './checkout-options'; -export { Checkout } from './checkout'; -export { CherrypickOptions } from './cherry-pick-options'; -export { Cherrypick } from './cherry-pick'; -export { CloneOptions } from './clone-options'; -export { Clone } from './clone'; -export { Commit } from './commit'; -export { Config } from './config'; -export { ConvenientHunk } from './convenient-hunk'; -export { ConvenientPatch } from './convenient-patch'; -export { CredUserpassPayload } from './cred-user-pass-payload'; -export { CredUsername } from './cred-username'; -export { Cred } from './cred'; -export { CvarMap } from './cvar-map'; -export { DescribeFormatOptions } from './describe-format-options'; -export { DescribeOptions } from './describe-options'; -export { DiffBinaryFile } from './diff-binary-file'; -export { DiffBinary } from './diff-binary'; -export { DiffDelta } from './diff-delta'; -export { DiffFile } from './diff-file'; -export { DiffLine } from './diff-line'; -export { DiffOptions } from './diff-options'; -export { DiffPerfdata } from './diff-perf-data'; -export { DiffStats } from './diff-stats'; -export { Diff, DiffFindOptions } from './diff'; -export { Enums } from './enums'; -export { Error } from './error'; -export { FetchOptions } from './fetch-options'; -export { Fetch } from './fetch'; -export { Filter } from './filter'; -export { Giterr } from './git-err'; -export { Graph } from './graph'; -export { Hashsig } from './hash-sig'; -export { Index } from './index_'; -export { IndexEntry } from './index-entry'; -export { Ignore } from './ignore'; -export { Indexer } from './indexer'; -export { Libgit2 } from './lib-git2'; -export { MergeFileInput } from './merge-file-input'; -export { MergeFileOptions } from './merge-file-options'; -export { MergeFileResult } from './merge-file-result'; -export { MergeOptions } from './merge-options'; -export { Merge } from './merge'; -export { Note } from './note'; -export { Object } from './object'; -export { OdbExpandId } from './odb-expand-id'; -export { OdbObject } from './odb-object'; -export { Odb } from './odb'; -export { Oidarray } from './oid-array'; -export { Oid } from './oid'; -export { Openssl } from './open-ssl'; -export { Packbuilder } from './pack-builder'; -export { Pathspec } from './path-spec'; -export { ProxyOptions } from './proxy-options'; -export { Proxy } from './proxy'; -export { PushOptions } from './push-options'; -export { PushUpdate } from './push-update'; -export { Push } from './push'; -export { RebaseOperation } from './rebase-operation'; -export { Rebase, RebaseOptions } from './rebase'; -export { Refdb } from './ref-db'; -export { Reflog, ReflogEntry } from './ref-log'; -export { Refspec } from './ref-spec'; -export { Reference } from './reference'; -export { RemoteCallbacks } from './remote-callbacks'; -export { Remote } from './remote'; -export { Repository, RepositoryInitOptions } from './repository'; -export { Reset } from './reset'; -export { Revparse } from './rev-parse'; -export { Revwalk } from './rev-walk'; -export { Revert } from './revert'; -export { Signature } from './signature'; -export { Stash } from './stash'; -export { StatusEntry } from './status-entry'; -export { StatusFileOptions } from './status-file-options'; -export { StatusFile } from './status-file'; -export { StatusList } from './status-list'; -export { StatusOptions } from './status-options'; -export { Status } from './status'; -export { Strarray } from './str-array'; -export { SubmoduleUpdateOptions } from './submodule-update-options'; -export { Submodule } from './submodule'; -export { Tag } from './tag'; -export { Time } from './time'; -export { TransferProgress } from './transfer-progress'; -export { Transport } from './transport'; -export { Treebuilder } from './tree-builder'; -export { TreeEntry } from './tree-entry'; -export { TreeUpdate } from './tree-update'; -export { Tree } from './tree'; -export const version: string; -declare const _: typeof Promise; -export { _ as Promise }; diff --git a/types/sosuisen__nodegit/index_.d.ts b/types/sosuisen__nodegit/index_.d.ts deleted file mode 100644 index 4d4a8206..00000000 --- a/types/sosuisen__nodegit/index_.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Oid } from './oid'; -import { IndexEntry } from './index-entry'; -import { Repository } from './repository'; -import { Tree } from './tree'; -import { Strarray } from './str-array'; - -export namespace Index { - const enum ADD_OPTION { - ADD_DEFAULT = 0, - ADD_FORCE = 1, - ADD_DISABLE_PATHSPEC_MATCH = 2, - ADD_CHECK_PATHSPEC = 4 - } - - const enum CAP { - IGNORE_CASE = 1, - NO_FILEMODE = 2, - NO_SYMLINKS = 4, - FROM_OWNER = -1 - } -} - -export class Index { - static entryIsConflict(entry: IndexEntry): boolean; - static entryStage(entry: IndexEntry): number; - static open(indexPath: string): Promise; - - add(sourceEntry: IndexEntry): number; - addAll(pathspec?: Strarray | string | string[], flags?: number, callback?: Function): Promise; - addByPath(path: string): Promise; - caps(): number; - checksum(): Oid; - clear(): number; - conflictAdd(ancestorEntry: IndexEntry, ourEntry: IndexEntry, theirEntry: IndexEntry): number; - conflictCleanup(): number; - conflictGet(path: string): Promise; - conflictRemove(path: string): number; - entryCount(): number; - getByIndex(n: number): IndexEntry; - getByPath(path: string, stage?: number): IndexEntry; - hasConflicts(): boolean; - owner(): Repository; - path(): string; - read(force: number): number; - readTree(tree: Tree): number; - remove(path: string, stage: number): number; - removeAll(pathspec: Strarray | string | string[], callback?: Function): Promise; - removeByPath(path: string): Promise; - removeDirectory(dir: string, stage: number): number; - setCaps(caps: number): number; - updateAll(pathspec: Strarray | string | string[], callback?: Function): Promise; - write(): Promise; - writeTree(): Promise; - writeTreeTo(repo: Repository): Promise; - entries(): IndexEntry[]; - findPrefix(atPos: number, prefix: string): number; - setVersion(version: number): number; - version(): number; -} diff --git a/types/sosuisen__nodegit/indexer.d.ts b/types/sosuisen__nodegit/indexer.d.ts deleted file mode 100644 index d4d3210b..00000000 --- a/types/sosuisen__nodegit/indexer.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { TransferProgress } from './transfer-progress'; -import { Oid } from './oid'; - -export class Indexer { - commit(stats: TransferProgress): number; - - free(): void; - hash(): Oid; -} diff --git a/types/sosuisen__nodegit/lib-git2.d.ts b/types/sosuisen__nodegit/lib-git2.d.ts deleted file mode 100644 index be5a5d18..00000000 --- a/types/sosuisen__nodegit/lib-git2.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -export namespace Libgit2 { - const enum OPT { - GET_MWINDOW_SIZE = 0, - SET_MWINDOW_SIZE = 1, - GET_MWINDOW_MAPPED_LIMIT = 2, - SET_MWINDOW_MAPPED_LIMIT = 3, - GET_SEARCH_PATH = 4, - SET_SEARCH_PATH = 5, - SET_CACHE_OBJECT_LIMIT = 6, - SET_CACHE_MAX_SIZE = 7, - ENABLE_CACHING = 8, - GET_CACHED_MEMORY = 9, - GET_TEMPLATE_PATH = 10, - SET_TEMPLATE_PATH = 11, - SET_SSL_CERT_LOCATIONS = 12 - } -} - -export class Libgit2 { - static features(): number; - static init(): number; - static opts(option: number): number; - static shutdown(): number; - static version(major: number, minor: number, rev: number): void; -} diff --git a/types/sosuisen__nodegit/merge-file-input.d.ts b/types/sosuisen__nodegit/merge-file-input.d.ts deleted file mode 100644 index f49bd446..00000000 --- a/types/sosuisen__nodegit/merge-file-input.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface MergeFileInput { - version: number; - ptr: string; - size: number; - path: string; - mode: number; -} diff --git a/types/sosuisen__nodegit/merge-file-options.d.ts b/types/sosuisen__nodegit/merge-file-options.d.ts deleted file mode 100644 index 861abaf9..00000000 --- a/types/sosuisen__nodegit/merge-file-options.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface MergeFileOptions { - version?: number; - ancestorLabel?: string; - ourLabel?: string; - theirLabel?: string; - favor?: number; - flags?: number; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/merge-file-result.d.ts b/types/sosuisen__nodegit/merge-file-result.d.ts deleted file mode 100644 index e6f2efcc..00000000 --- a/types/sosuisen__nodegit/merge-file-result.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class MergeFileResult { - automergeable: number; - path: string; - mode: number; - ptr: string; - len: number; -} diff --git a/types/sosuisen__nodegit/merge-options.d.ts b/types/sosuisen__nodegit/merge-options.d.ts deleted file mode 100644 index 51494220..00000000 --- a/types/sosuisen__nodegit/merge-options.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export class MergeOptions { - version?: number; - renameThreshold?: number; - targetLimit?: number; - fileFavor?: number; - fileFlags?: number; - defaultDriver?: string; - flags?: number; - recursionLimit?: number; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/merge.d.ts b/types/sosuisen__nodegit/merge.d.ts deleted file mode 100644 index 4233b725..00000000 --- a/types/sosuisen__nodegit/merge.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; -import { Tree } from './tree'; -import { Commit } from './commit'; -import { Index } from './index'; -import { AnnotatedCommit } from './annotated-commit'; -import { CheckoutOptions } from './checkout-options'; -import { Oidarray } from './oid-array'; -import { MergeOptions } from './merge-options'; -import { MergeFileInput } from './merge-file-input'; - -export namespace Merge { - const enum ANALYSIS { - NONE = 0, - NORMAL = 1, - UP_TO_DATE = 2, - FASTFORWARD = 4, - UNBORN = 8 - } - - const enum FILE_FAVOR { - NORMAL = 0, - OURS = 1, - THEIRS = 2, - UNION = 3 - } - - const enum FILE_FLAGS { - FILE_DEFAULT = 0, - FILE_STYLE_MERGE = 1, - FILE_STYLE_DIFF3 = 2, - FILE_SIMPLIFY_ALNUM = 4, - FILE_IGNORE_WHITESPACE = 8, - FILE_IGNORE_WHITESPACE_CHANGE = 16, - FILE_IGNORE_WHITESPACE_EOL = 32, - FILE_DIFF_PATIENCE = 64, - FILE_DIFF_MINIMAL = 128 - } - - const enum PREFERENCE { - NONE = 0, - NO_FASTFORWARD = 1, - FASTFORWARD_ONLY = 2 - } - - const enum TREE_FLAG { - TREE_FIND_RENAMES = 1 - } -} - -export class Merge { - static merge(repo: Repository, theirHead: AnnotatedCommit, mergeOpts?: MergeOptions, checkoutOpts?: CheckoutOptions): any; - static base(repo: Repository, one: Oid, two: Oid): Promise; - static bases(repo: Repository, one: Oid, two: Oid): Promise; - static commits(repo: Repository, ourCommit: Commit, theirCommit: Commit, options?: MergeOptions): any; - static fileInitInput(opts: MergeFileInput, version: number): number; - static initOptions(opts: MergeOptions, version: number): number; - static trees(repo: Repository, ancestorTree: Tree, ourTree: Tree, theirTree: Tree, opts?: MergeOptions): Promise; -} diff --git a/types/sosuisen__nodegit/note.d.ts b/types/sosuisen__nodegit/note.d.ts deleted file mode 100644 index b2c196c3..00000000 --- a/types/sosuisen__nodegit/note.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Repository } from './repository'; -import { Signature } from './signature'; -import { Oid } from './oid'; - -export class Note { - static create(repo: Repository, notesRef: string, author: Signature, committer: Signature, oid: Oid, note: string, force: number): Promise; - static foreach(repo: Repository, notesRef: string, noteCb: Function, payload: any): Promise; - static iteratorNew(repo: Repository, notesRef: string): Promise; - static next(noteId: Oid, annotatedId: Oid, it: any): number; - static read(repo: Repository, notesRef: string, oid: Oid): Promise; - static remove(repo: Repository, notesRef: string, author: Signature, committer: Signature, oid: Oid): Promise; - - author(): Signature; - committer(): Signature; - - free(): void; - id(): Oid; - message(): string; -} diff --git a/types/sosuisen__nodegit/object.d.ts b/types/sosuisen__nodegit/object.d.ts deleted file mode 100644 index be7e879b..00000000 --- a/types/sosuisen__nodegit/object.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Oid } from './oid'; -import { Repository } from './repository'; -import { Buf } from './buf'; - -export class Object { - static size(type: Object.TYPE): number; - static lookup(repo: Repository, id: Oid, type: Object.TYPE): Promise; - static lookupPrefix(repo: Repository, id: Oid, len: number, type: Object.TYPE): Promise; - static string2Type(str: string): Object.TYPE; - static type2String(type: Object.TYPE): string; - static typeisloose(type: Object.TYPE): number; - - dup(): Promise; - - free(): void; - id(): Oid; - lookupByPath(path: string, type: Object.TYPE): Promise; - owner(): Repository; - peel(targetType: number): Promise; - shortId(): Promise; - type(): number; -} - -export namespace Object { - const enum TYPE { - ANY = -2, - BAD = -1, - EXT1 = 0, - COMMIT = 1, - TREE = 2, - BLOB = 3, - TAG = 4, - EXT2 = 5, - OFS_DELTA = 6, - REF_DELTA = 7 - } -} diff --git a/types/sosuisen__nodegit/odb-expand-id.d.ts b/types/sosuisen__nodegit/odb-expand-id.d.ts deleted file mode 100644 index 5576fbad..00000000 --- a/types/sosuisen__nodegit/odb-expand-id.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Oid } from './oid'; -import { Object } from './object'; - -export class OdbExpandId { - id: Oid; - length: number; - type: Object.TYPE; -} diff --git a/types/sosuisen__nodegit/odb-object.d.ts b/types/sosuisen__nodegit/odb-object.d.ts deleted file mode 100644 index 9685f282..00000000 --- a/types/sosuisen__nodegit/odb-object.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Oid } from './oid'; - -export class OdbObject { - data(): Buffer; - dup(): Promise; - - free(): void; - id(): Oid; - size(): number; - type(): number; -} diff --git a/types/sosuisen__nodegit/odb.d.ts b/types/sosuisen__nodegit/odb.d.ts deleted file mode 100644 index e5348d08..00000000 --- a/types/sosuisen__nodegit/odb.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Oid } from './oid'; -import { OdbObject } from './odb-object'; -import { OdbExpandId } from './odb-expand-id'; -import { Object } from './object'; - -export namespace Odb { - const enum STREAM { - RDONLY = 2, - WRONLY = 4, - RW = 6 - } -} - -export class Odb { - static open(objectsDir: string): Promise; - - addDiskAlternate(path: string): number; - - free(): void; - read(id: Oid): Promise; - write(data: Buffer, len: number, type: Object.TYPE): Promise; - expandIds(ids: OdbExpandId, count: number): number; -} diff --git a/types/sosuisen__nodegit/oid-array.d.ts b/types/sosuisen__nodegit/oid-array.d.ts deleted file mode 100644 index 7a96f24a..00000000 --- a/types/sosuisen__nodegit/oid-array.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Oid } from './oid'; - -export class Oidarray { - free(): void; - ids: Oid; - count: number; -} diff --git a/types/sosuisen__nodegit/oid.d.ts b/types/sosuisen__nodegit/oid.d.ts deleted file mode 100644 index 2aa65905..00000000 --- a/types/sosuisen__nodegit/oid.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export class Oid { - static fromString(str: string): Oid; - cmp(b: Oid): number; - cpy(): Oid; - equal(b: Oid): number; - iszero(): number; - ncmp(b: Oid, len: number): number; - strcmp(str: string): number; - streq(str: string): number; - tostrS(): string; -} diff --git a/types/sosuisen__nodegit/open-ssl.d.ts b/types/sosuisen__nodegit/open-ssl.d.ts deleted file mode 100644 index f8370260..00000000 --- a/types/sosuisen__nodegit/open-ssl.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class Openssl { - static setLocking(): number; -} diff --git a/types/sosuisen__nodegit/pack-builder.d.ts b/types/sosuisen__nodegit/pack-builder.d.ts deleted file mode 100644 index ed0fa0a2..00000000 --- a/types/sosuisen__nodegit/pack-builder.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; -import { Revwalk } from './rev-walk'; - -export namespace Packbuilder { - const enum STAGE { - ADDING_OBJECTS = 0, - DELTAFICATION = 1 - } -} - -export class Packbuilder { - static create(repo: Repository): Packbuilder; - - free(): void; - hash(): Oid; - insert(id: Oid, name: string): number; - insertCommit(id: Oid): number; - insertRecur(id: Oid, name: string): number; - insertTree(id: Oid): number; - insertWalk(walk: Revwalk): number; - objectCount(): number; - setThreads(n: number): number; - written(): number; -} diff --git a/types/sosuisen__nodegit/package.json b/types/sosuisen__nodegit/package.json deleted file mode 100644 index 1daf887a..00000000 --- a/types/sosuisen__nodegit/package.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "_args": [ - [ - "@types/nodegit@0.26.12", - "I:\\working_src\\git-documentdb" - ] - ], - "_development": true, - "_from": "@types/nodegit@0.26.12", - "_id": "@types/nodegit@0.26.12", - "_inBundle": false, - "_integrity": "sha512-4YpeTImFZNJ1cve4lEueHFVS8rAs8XpZqlmx+Bm9bMc+XMiCrcwaUf6peN7pod7Rl3esVlGP1zdBB7Z12eMVAA==", - "_location": "/@types/nodegit", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "@types/nodegit@0.26.12", - "name": "@types/nodegit", - "escapedName": "@types%2fnodegit", - "scope": "@types", - "rawSpec": "0.26.12", - "saveSpec": null, - "fetchSpec": "0.26.12" - }, - "_requiredBy": [ - "#DEV:/" - ], - "_resolved": "https://registry.npmjs.org/@types/nodegit/-/nodegit-0.26.12.tgz", - "_spec": "0.26.12", - "_where": "I:\\working_src\\git-documentdb", - "bugs": { - "url": "https://github.com/DefinitelyTyped/DefinitelyTyped/issues" - }, - "contributors": [ - { - "name": "Dolan Miu", - "url": "https://github.com/dolanmiu" - }, - { - "name": "Tobias Nießen", - "url": "https://github.com/tniessen" - }, - { - "name": "Pierre Vigier", - "url": "https://github.com/pvigier" - }, - { - "name": "Jibril Saffi", - "url": "https://github.com/IGI-111" - }, - { - "name": "Benjamin Schuster-Boeckler", - "url": "https://github.com/DaGaMs" - }, - { - "name": "Julien Chaumond", - "url": "https://github.com/julien-c" - } - ], - "dependencies": { - "@types/node": "*" - }, - "description": "TypeScript definitions for nodegit", - "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped#readme", - "license": "MIT", - "main": "", - "name": "@types/nodegit", - "repository": { - "type": "git", - "url": "git+https://github.com/DefinitelyTyped/DefinitelyTyped.git", - "directory": "types/nodegit" - }, - "scripts": {}, - "typeScriptVersion": "3.2", - "types": "index.d.ts", - "typesPublisherContentHash": "18ca2b36bafcdb66a752360fe388e3fe585bac07d9e3e835a0ec2cf4f49f92ae", - "version": "0.26.12" -} diff --git a/types/sosuisen__nodegit/path-spec.d.ts b/types/sosuisen__nodegit/path-spec.d.ts deleted file mode 100644 index 31b58f01..00000000 --- a/types/sosuisen__nodegit/path-spec.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { DiffDelta } from './diff-delta'; -import { Tree } from './tree'; -import { Diff } from './diff'; -import { Repository } from './repository'; -import { Index } from './index'; -import { Strarray } from './str-array'; - -export namespace Pathspec { - const enum FLAG { - DEFAULT = 0, - IGNORE_CASE = 1, - USE_CASE = 2, - NO_GLOB = 4, - NO_MATCH_ERROR = 8, - FIND_FAILURES = 16, - FAILURES_ONLY = 32 - } -} - -export class Pathspec { - static matchListDiffEntry(m: any, pos: number): DiffDelta; - static matchListEntry(m: any, pos: number): string; - static matchListEntrycount(m: any): number; - static matchListFailedEntry(m: any, pos: number): string; - static matchListFailedEntrycount(m: any): number; - static create(pathspec: Strarray | string | string[]): Pathspec; - - free(): void; - matchDiff(diff: Diff, flags: number): Promise; - matchIndex(index: Index, flags: number): Promise; - matchTree(tree: Tree, flags: number): Promise; - matchWorkdir(repo: Repository, flags: number): Promise; - matchesPath(flags: number, path: string): number; -} diff --git a/types/sosuisen__nodegit/proxy-options.d.ts b/types/sosuisen__nodegit/proxy-options.d.ts deleted file mode 100644 index 88f73483..00000000 --- a/types/sosuisen__nodegit/proxy-options.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class ProxyOptions { - certificateCheck?: Function; - credentials?: Function; - payload?: any; - type?: number; - url?: string; - version?: number; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/proxy.d.ts b/types/sosuisen__nodegit/proxy.d.ts deleted file mode 100644 index 8b4806a2..00000000 --- a/types/sosuisen__nodegit/proxy.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ProxyOptions } from './proxy-options'; - -export class Proxy { - static initOptions(opts: ProxyOptions, version: number): number; -} diff --git a/types/sosuisen__nodegit/push-options.d.ts b/types/sosuisen__nodegit/push-options.d.ts deleted file mode 100644 index 5f7625db..00000000 --- a/types/sosuisen__nodegit/push-options.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { RemoteCallbacks } from './remote-callbacks'; -import { Strarray } from './str-array'; -import { ProxyOptions } from './proxy-options'; - -export interface PushOptions { - version?: number; - pbParallelism?: number; - callbacks?: RemoteCallbacks; - customHeaders?: Strarray | string | string[]; - proxyOpts?: ProxyOptions; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/push-update.d.ts b/types/sosuisen__nodegit/push-update.d.ts deleted file mode 100644 index 50f46726..00000000 --- a/types/sosuisen__nodegit/push-update.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Oid } from './oid'; - -export class PushUpdate { - srcRefname: string; - dstRefname: string; - src: Oid; - dst: Oid; -} diff --git a/types/sosuisen__nodegit/push.d.ts b/types/sosuisen__nodegit/push.d.ts deleted file mode 100644 index 26d8f07b..00000000 --- a/types/sosuisen__nodegit/push.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { RemoteCallbacks } from './remote-callbacks'; -import { PushOptions } from './push-options'; - -export class Push { - static initOptions(opts: PushOptions, version: number): number; -} diff --git a/types/sosuisen__nodegit/rebase-operation.d.ts b/types/sosuisen__nodegit/rebase-operation.d.ts deleted file mode 100644 index 7144ebe6..00000000 --- a/types/sosuisen__nodegit/rebase-operation.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Oid } from './oid'; - -export namespace RebaseOperation { - const enum REBASE_OPERATION { - PICK = 0, - REWORD = 1, - EDIT = 2, - SQUASH = 3, - FIXUP = 4, - EXEC = 5 - } -} - -export class RebaseOperation { - type: number; - id: Oid; - exec: string; -} diff --git a/types/sosuisen__nodegit/rebase.d.ts b/types/sosuisen__nodegit/rebase.d.ts deleted file mode 100644 index be0b5d2c..00000000 --- a/types/sosuisen__nodegit/rebase.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CheckoutOptions } from './checkout-options'; -import { AnnotatedCommit } from './annotated-commit'; -import { Repository } from './repository'; -import { Signature } from './signature'; -import { Oid } from './oid'; -import { RebaseOperation } from './rebase-operation'; -import { Index } from './index'; - -export interface RebaseOptions { - version: number; - quiet: number; - rewriteNotesRef: string; - checkoutOptions: CheckoutOptions; -} - -export class Rebase { - static init(repo: Repository, branch: AnnotatedCommit, upstream: AnnotatedCommit, onto: AnnotatedCommit, opts?: RebaseOptions): Promise; - static initOptions(opts: RebaseOptions, version: number): number; - static open(repo: Repository, opts?: RebaseOptions): Promise; - - abort(): number; - commit(author: Signature, committer: Signature, messageEncoding: string, message: string): Oid; - finish(signature: Signature): number; - inmemoryIndex(index: Index): number; - next(): Promise; - operationByIndex(idx: number): RebaseOperation; - operationCurrent(): number; - operationEntrycount(): number; -} diff --git a/types/sosuisen__nodegit/ref-db.d.ts b/types/sosuisen__nodegit/ref-db.d.ts deleted file mode 100644 index 6a5701ff..00000000 --- a/types/sosuisen__nodegit/ref-db.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Repository } from './repository'; - -export class Refdb { - static open(repo: Repository): Promise; - - compress(): number; - - free(): void; -} diff --git a/types/sosuisen__nodegit/ref-log.d.ts b/types/sosuisen__nodegit/ref-log.d.ts deleted file mode 100644 index ac43de7e..00000000 --- a/types/sosuisen__nodegit/ref-log.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; -import { Signature } from './signature'; - -export class Reflog { - static delete(repo: Repository, name: string): number; - static read(repo: Repository, name: string): Promise; - static rename(repo: Repository, oldName: string, name: string): number; - - append(id: Oid, committer: Signature, msg: string): number; - drop(idx: number, rewritePreviousEntry: number): number; - entryByIndex(idx: number): ReflogEntry; - entrycount(): number; - - free(): void; - write(): number; -} - -export class ReflogEntry { - committer(): Signature; - idNew(): Oid; - idOld(): Oid; - message(): string; -} diff --git a/types/sosuisen__nodegit/ref-spec.d.ts b/types/sosuisen__nodegit/ref-spec.d.ts deleted file mode 100644 index bf40f21a..00000000 --- a/types/sosuisen__nodegit/ref-spec.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export class Refspec { - direction(): number; - dst(): string; - dstMatches(refname: string): number; - force(): number; - src(): string; - srcMatches(refname: string): number; -} diff --git a/types/sosuisen__nodegit/reference.d.ts b/types/sosuisen__nodegit/reference.d.ts deleted file mode 100644 index cc6cb90e..00000000 --- a/types/sosuisen__nodegit/reference.d.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; -import { Object } from './object'; - -export namespace Reference { - const enum TYPE { - INVALID = 0, - OID = 1, - SYMBOLIC = 2, - LISTALL = 3 - } - - const enum NORMALIZE { - REF_FORMAT_NORMAL = 0, - REF_FORMAT_ALLOW_ONELEVEL = 1, - REF_FORMAT_REFSPEC_PATTERN = 2, - REF_FORMAT_REFSPEC_SHORTHAND = 4 - } -} - -export class Reference { - static create(repo: Repository, name: string, id: Oid, force: number, logMessage: string): Promise; - static createMatching(repo: Repository, name: string, id: Oid, force: number, currentId: Oid, logMessage: string): Promise; - static dwim(repo: Repository, id: string | Reference, callback?: Function): Promise; - static ensureLog(repo: Repository, refname: string): number; - static hasLog(repo: Repository, refname: string): number; - static isValidName(refname: string): number; - static list(repo: Repository): Promise; - static lookup(repo: Repository, id: string | Reference, callback?: Function): Promise; - static nameToId(repo: Repository, name: string): Promise; - static normalizeName(bufferOut: string, bufferSize: number, name: string, flags: number): number; - static remove(repo: Repository, name: string): number; - static symbolicCreate(repo: Repository, name: string, target: string, force: number, logMessage: string): Promise; - static symbolicCreateMatching(repo: Repository, name: string, target: string, force: number, currentValue: string, logMessage: string): Promise; - - cmp(ref2: Reference): number; - delete(): number; - isBranch(): number; - isNote(): number; - isRemote(): number; - isTag(): number; - name(): string; - owner(): Repository; - peel(type: Object.TYPE): Promise; - rename(newName: string, force: number, logMessage: string): Promise; - resolve(): Promise; - setTarget(id: Oid, logMessage: string): Promise; - shorthand(): string; - symbolicSetTarget(target: string, logMessage: string): Promise; - symbolicTarget(): string; - target(): Oid; - targetPeel(): Oid; - type(): number; - isValid(): boolean; - isConcrete(): boolean; - isSymbolic(): boolean; - toString(): string; - isHead(): boolean; - dup(): Promise; -} diff --git a/types/sosuisen__nodegit/remote-callbacks.d.ts b/types/sosuisen__nodegit/remote-callbacks.d.ts deleted file mode 100644 index ca244e5c..00000000 --- a/types/sosuisen__nodegit/remote-callbacks.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export class RemoteCallbacks { - version?: number; - credentials?: Function; - certificateCheck?: Function; - transferProgress?: Function; - transport?: Function; - payload?: undefined; -} diff --git a/types/sosuisen__nodegit/remote.d.ts b/types/sosuisen__nodegit/remote.d.ts deleted file mode 100644 index a8525645..00000000 --- a/types/sosuisen__nodegit/remote.d.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Repository } from './repository'; -import { RemoteCallbacks } from './remote-callbacks'; -import { Strarray } from './str-array'; -import { FetchOptions } from './fetch-options'; -import { Buf } from './buf'; -import { Enums } from './enums'; -import { TransferProgress } from './transfer-progress'; -import { PushOptions } from './push-options'; -import { Refspec } from './ref-spec'; - -export namespace Remote { - const enum AUTOTAG_OPTION { - DOWNLOAD_TAGS_UNSPECIFIED = 0, - DOWNLOAD_TAGS_AUTO = 1, - DOWNLOAD_TAGS_NONE = 2, - DOWNLOAD_TAGS_ALL = 3 - } - - const enum COMPLETION_TYPE { - COMPLETION_DOWNLOAD = 0, - COMPLETION_INDEXING = 1, - COMPLETION_ERROR = 2 - } -} - -export class Remote { - static addFetch(repo: Repository, remote: string, refspec: string): number; - static addPush(repo: Repository, remote: string, refspec: string): number; - static create(repo: Repository, name: string, url: string): Promise; - static createAnonymous(repo: Repository, url: string): Promise; - static createDetached(url: string): Promise; - static createWithFetchspec(repo: Repository, name: string, url: string, fetch: string): Promise; - static delete(repo: Repository, name: string): Promise; - static initCallbacks(opts: RemoteCallbacks, version: number): number; - static isValidName(remoteName: string): boolean; - static list(repo: Repository): Promise; - static lookup(repo: Repository, name: string | Remote, callback?: Function): Promise; - static setAutotag(repo: Repository, remote: string, value: number): number; - static setPushurl(repo: Repository, remote: string, url: string): number; - static setUrl(repo: Repository, remote: string, url: string): number; - - autotag(): number; - connect(direction: Enums.DIRECTION, callbacks: RemoteCallbacks, callback?: Function): Promise; - connected(): number; - defaultBranch(): Promise; - disconnect(): Promise; - download(refSpecs: any[], opts?: FetchOptions, callback?: Function): Promise; - dup(): Promise; - fetch(refSpecs: any[], opts: FetchOptions, message: string, callback?: Function): Promise; - - free(): void; - getFetchRefspecs(): Promise; - getPushRefspecs(): Promise; - getRefspec(n: number): Refspec; - name(): string; - owner(): Repository; - prune(callbacks: RemoteCallbacks): number; - pruneRefs(): number; - push(refSpecs: any[], options?: PushOptions, callback?: Function): Promise; - pushurl(): string; - refspecCount(): number; - stats(): TransferProgress; - - stop(): void; - updateTips(callbacks: RemoteCallbacks, updateFetchhead: number, downloadTags: number, reflogMessage: string): number; - upload(refspecs: Strarray | string | string[], opts?: PushOptions): number; - url(): string; - /** - * Lists advertised references from a remote. You must connect to the remote before using referenceList. - */ - referenceList(): Promise; -} diff --git a/types/sosuisen__nodegit/repository.d.ts b/types/sosuisen__nodegit/repository.d.ts deleted file mode 100644 index 31ce4df6..00000000 --- a/types/sosuisen__nodegit/repository.d.ts +++ /dev/null @@ -1,249 +0,0 @@ -import { Oid } from './oid'; -import { Buf } from './buf'; -import { Reference } from './reference'; -import { Odb } from './odb'; -import { Object } from './object'; -import { Index } from './index_'; -import { Commit } from './commit'; -import { Blob } from './blob'; -import { Tree } from './tree'; -import { Signature } from './signature'; -import { AnnotatedCommit } from './annotated-commit'; -import { FetchOptions } from './fetch-options'; -import { CheckoutOptions } from './checkout-options'; -import { Remote } from './remote'; -import { Tag } from './tag'; -import { Config } from './config'; -import { Merge } from './merge'; -import { MergeOptions } from './merge-options'; -import { Refdb } from './ref-db'; -import { Revwalk } from './rev-walk'; -import { StatusFile } from './status-file'; -import { StatusOptions } from './status-options'; -import { DiffLine } from './diff-line'; -import { Treebuilder } from './tree-builder'; - -export interface RepositoryInitOptions { - description: string; - flags: number; - initialHead: string; - mode: number; - originUrl: string; - templatePath: string; - version: number; - workdirPath: string; -} - -export class Repository { - /** - * Creates a branch with the passed in name pointing to the commit - */ - static discover(startPath: string, acrossFs: number, ceilingDirs: string): Promise; - static init(path: string, isBare: number): Promise; - static initExt(repoPath: string, options?: RepositoryInitOptions): Promise; - static open(path: string): Promise; - static openBare(barePath: string): Promise; - static openExt(path: string, flags?: number, ceilingDirs?: string): Promise; - static wrapOdb(odb: Odb): Promise; - - cleanup(): void; - commondir(): string; - config(): Promise; - configSnapshot(): Promise; - detachHead(): number; - fetchheadForeach(callback?: Function): Promise; - - free(): void; - getNamespace(): string; - head(): Promise; - headDetached(): number; - headUnborn(): number; - index(): Promise; - isBare(): number; - isEmpty(): number; - isShallow(): number; - mergeheadForeach(callback?: Function): Promise; - messageRemove(): number; - odb(): Promise; - path(): string; - refdb(): Promise; - setHead(refname: string): Promise; - setHeadDetached(commitish: Oid): number; - setHeadDetachedFromAnnotated(commitish: AnnotatedCommit): number; - setIdent(name: string, email: string): number; - setNamespace(nmspace: string): number; - setWorkdir(workdir: string, updateGitLink: number): number; - state(): number; - stateCleanup(): number; - workdir(): string; - /** - * Creates a branch with the passed in name pointing to the commit - */ - createBranch(name: string, commit: Commit | string | Oid, force?: boolean): Promise; - /** - * Look up a refs's commit. - */ - getReferenceCommit(name: string | Reference): Promise; - /** - * Look up a branch. Alias for getReference - */ - getBranch(name: string | Reference): Promise; - /** - * Look up a branch's most recent commit. Alias to getReferenceCommit - */ - getBranchCommit(name: string | Reference): Promise; - /** - * Gets the branch that HEAD currently points to Is an alias to head() - */ - getCurrentBranch(): Promise; - /** - * Lookup the reference with the given name. - */ - getReference(name: string | Reference): Promise; - /** - * Lookup references for a repository. - */ - getReferences(): Promise; - /** - * Lookup reference names for a repository. - */ - getReferenceNames(type: Reference.TYPE): Promise; - getCommit(string: string | Commit| Oid): Promise; - /** - * Retrieve the blob represented by the oid. - */ - getBlob(string: string | Oid): Promise; - /** - * Retrieve the tree represented by the oid. - */ - getTree(string: string | Oid): Promise; - createTag(string: string | Oid, name: string, message: string): Promise; - /** - * Creates a new lightweight tag - */ - createLightweightTag(string: string | Oid, name: string): Promise; - /** - * Retrieve the tag represented by the oid. - */ - getTag(string: string | Oid): Promise; - /** - * Retrieve the tag represented by the tag name. - */ - getTagByName(Short: string): Promise; - /** - * Deletes a tag from a repository by the tag name. - */ - deleteTagByName(Short: string): Promise; - /** - * Instantiate a new revision walker for browsing the Repository"s history. See also Commit.prototype.history() - */ - createRevWalk(): Revwalk; - /** - * Retrieve the master branch commit. - */ - getMasterCommit(): Promise; - /** - * Retrieve the commit that HEAD is currently pointing to - */ - getHeadCommit(): Promise; - createCommit(updateRef: string, author: Signature, committer: Signature, message: string, Tree: Tree | Oid | string, parents: Array, callback?: Function): Promise; - /** - * Creates a new commit on HEAD from the list of passed in files - */ - createCommitOnHead(filesToAdd: string[], author: Signature, committer: Signature, message: string): Promise; - /** - * Create a blob from a buffer - */ - createBlobFromBuffer(buffer: Buffer): Promise; - treeBuilder(tree: Tree): Promise; - /** - * Gets the default signature for the default user and now timestamp - */ - defaultSignature(): Signature; - /** - * Lists out the remotes in the given repository. - */ - getRemotes(callback?: Function): Promise; - /** - * Gets a remote from the repo - */ - getRemote(remote: string | Remote, callback?: Function): Promise; - /** - * Fetches from a remote - */ - fetch(remote: string | Remote, fetchOptions?: FetchOptions): Promise; - /** - * Fetches from all remotes. This is done in series due to deadlocking issues with fetching from many remotes that can happen. - */ - fetchAll(fetchOptions?: FetchOptions, callback?: Function): Promise; - mergeBranches(to: string | Reference, from: string | Reference, signature?: Signature, mergePreference?: Merge.PREFERENCE, mergeOptions?: MergeOptions): Promise; - /** - * Rebases a branch onto another branch - */ - rebaseBranches(branch: string, upstream: string, onto: string, signature: Signature, beforeNextFn: Function): Promise; - continueRebase(signature: Signature, beforeNextFn: Function): Promise; - /** - * Get the status of a repo to it's working directory - */ - getStatus(opts?: StatusOptions): Promise; - /** - * Get extended statuses of a repo to it's working directory. Status entries have status, headToIndex delta, and indexToWorkdir deltas - */ - getStatusExt(opts?: StatusOptions): Promise; - /** - * Get the names of the submodules in the repository. - */ - getSubmoduleNames(): Promise; - /** - * This will set the HEAD to point to the reference and then attempt to update the index and working tree to match the content of the latest commit on that reference - */ - checkoutRef(reference: Reference, opts?: CheckoutOptions): Promise; - /** - * This will set the HEAD to point to the local branch and then attempt to update the index and working tree to match the content of the latest commit on that branch - */ - checkoutBranch(branch: string | Reference, opts?: CheckoutOptions): Promise; - /** - * Stages or unstages line selection of a specified file - */ - stageFilemode(filePath: string | string[], stageNew: boolean): Promise; - /** - * Stages or unstages line selection of a specified file - */ - stageLines(filePath: string, newLines: DiffLine[], isStaged: boolean): Promise; - /** - * Returns true if the repository is in the default NONE state. - */ - isDefaultState(): boolean; - /** - * Returns true if the repository is in the APPLY_MAILBOX or APPLY_MAILBOX_OR_REBASE state. - */ - isApplyingMailbox(): boolean; - /** - * Returns true if the repository is in the BISECT state. - */ - isBisecting(): boolean; - /** - * Returns true if the repository is in the CHERRYPICK state. - */ - isCherrypicking(): boolean; - /** - * Returns true if the repository is in the MERGE state. - */ - isMerging(): boolean; - /** - * Returns true if the repository is in the REBASE, REBASE_INTERACTIVE, or REBASE_MERGE state. - */ - isRebasing(): boolean; - /** - * Returns true if the repository is in the REVERT state. - */ - isReverting(): boolean; - /** - * Discard line selection of a specified file. Assumes selected lines are unstaged. - */ - discardLines(filePath: string, selectedLines: DiffLine[]): Promise; - /** - * Grabs a fresh copy of the index from the repository. Invalidates all previously grabbed indexes - */ - refreshIndex(): Promise; -} diff --git a/types/sosuisen__nodegit/reset.d.ts b/types/sosuisen__nodegit/reset.d.ts deleted file mode 100644 index ca7ff41e..00000000 --- a/types/sosuisen__nodegit/reset.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { AnnotatedCommit } from './annotated-commit'; -import { Repository } from './repository'; -import { Strarray } from './str-array'; -import { CheckoutOptions } from './checkout-options'; -import { Commit } from './commit'; -import { Tag } from './tag'; - -export namespace Reset { - const enum TYPE { - SOFT = 1, - MIXED = 2, - HARD = 3 - } -} - -export class Reset { - /** - * Look up a refs's commit. - */ - static reset(repo: Repository, target: Commit | Tag, resetType: number, checkoutOpts: CheckoutOptions): Promise; - /** - * Look up a refs's commit. - */ - static default(repo: Repository, target: Commit | Tag, pathspecs: Strarray | string | string[]): Promise; - /** - * Sets the current head to the specified commit oid and optionally resets the index and working tree to match. - * This behaves like reset but takes an annotated commit, which lets you specify which extended sha syntax string was specified by a user, allowing for more exact reflog messages. - * See the documentation for reset. - */ - static fromAnnotated(repo: Repository, commit: AnnotatedCommit, resetType: number, checkoutOpts: CheckoutOptions): number; -} diff --git a/types/sosuisen__nodegit/rev-parse.d.ts b/types/sosuisen__nodegit/rev-parse.d.ts deleted file mode 100644 index c878b791..00000000 --- a/types/sosuisen__nodegit/rev-parse.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Object } from './object'; -import { Repository } from './repository'; -import { Reference } from './reference'; - -export namespace Revparse { - const enum MODE { - SINGLE = 1, - RANGE = 2, - MERGE_BASE = 4 - } -} - -export class Revparse { - static ext(objectOut: Object, referenceOut: Reference, repo: Repository, spec: string): number; - static single(repo: Repository, spec: string): Promise; -} diff --git a/types/sosuisen__nodegit/rev-walk.d.ts b/types/sosuisen__nodegit/rev-walk.d.ts deleted file mode 100644 index 38975315..00000000 --- a/types/sosuisen__nodegit/rev-walk.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; -import { Commit } from './commit'; - -export namespace Revwalk { - const enum SORT { - NONE = 0, - TOPOLOGICAL = 1, - TIME = 2, - REVERSE = 4 - } -} - -export class Revwalk { - static create(repo: Repository): Revwalk; - - hide(commitId: Oid): number; - hideGlob(glob: string): number; - hideHead(): number; - hideRef(refname: string): number; - next(): Promise; - push(id: Oid): number; - pushGlob(glob: string): number; - pushHead(): number; - pushRange(range: string): number; - pushRef(refname: string): number; - repository(): Repository; - - reset(): void; - - simplifyFirstParent(): void; - /** - * Set the sort order for the revwalk. This function takes variable arguments like revwalk.sorting(NodeGit.RevWalk.Topological, NodeGit.RevWalk.Reverse). - */ - sorting(...sort: number[]): void; - fastWalk(maxCount: number): Promise; - fileHistoryWalk(filePath: string, maxCount: number): Promise; - /** - * Walk the history from the given oid. The callback is invoked for each commit; When the walk is over, the callback is invoked with (null, null). - */ - walk(oid: Oid, callback?: Function): Commit; - /** - * Walk the history grabbing commits until the checkFn called with the current commit returns false. - */ - getCommitsUntil(checkFn: Function): Promise; - getCommits(count: number): Promise; -} diff --git a/types/sosuisen__nodegit/revert.d.ts b/types/sosuisen__nodegit/revert.d.ts deleted file mode 100644 index df804cbb..00000000 --- a/types/sosuisen__nodegit/revert.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MergeOptions } from './merge-options'; -import { CheckoutOptions } from './checkout-options'; -import { Repository } from './repository'; -import { Commit } from './commit'; -import { Index } from './index'; - -export interface RevertOptions { - version?: number; - mainline?: number; - mergeOpts?: MergeOptions; - checkoutOpts?: CheckoutOptions; - [key: string]: any; -} - -export class Revert { - static revert(repo: Repository, commit: Commit, givenOpts?: RevertOptions): Promise; - /** - * Reverts the given commit against the given "our" commit, producing an index that reflects the result of the revert. - */ - static commit(repo: Repository, revertCommit: Commit, ourCommit: Commit, mainline: number, mergeOptions?: MergeOptions): Promise; -} diff --git a/types/sosuisen__nodegit/signature.d.ts b/types/sosuisen__nodegit/signature.d.ts deleted file mode 100644 index 93e76fd6..00000000 --- a/types/sosuisen__nodegit/signature.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Repository } from './repository'; -import { Time } from './time'; - -export class Signature { - static default(repo: Repository): Signature; - static create(name: string, email: string, time: number, offset: number): Signature; - static now(name: string, email: string): Signature; - static fromBuffer(buf: string): Promise; - - dup(): Promise; - - free(): void; - toString(): string; - name(): string; - email(): string; - when(): Time; -} diff --git a/types/sosuisen__nodegit/stash.d.ts b/types/sosuisen__nodegit/stash.d.ts deleted file mode 100644 index 68d61d0e..00000000 --- a/types/sosuisen__nodegit/stash.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Repository } from './repository'; -import { Signature } from './signature'; -import { Oid } from './oid'; -import { CheckoutOptions } from './checkout-options'; - -export namespace Stash { - const enum APPLY_FLAGS { - APPLY_DEFAULT = 0, - APPLY_REINSTATE_INDEX = 1 - } - - const enum APPLY_PROGRESS { - NONE = 0, - LOADING_STASH = 1, - ANALYZE_INDEX = 2, - ANALYZE_MODIFIED = 3, - ANALYZE_UNTRACKED = 4, - CHECKOUT_UNTRACKED = 5, - CHECKOUT_MODIFIED = 6, - DONE = 7 - } - - const enum FLAGS { - DEFAULT = 0, - KEEP_INDEX = 1, - INCLUDE_UNTRACKED = 2, - INCLUDE_IGNORED = 4 - } -} - -export interface StashApplyOptions { - version?: number; - flags?: number; - checkoutOptions?: CheckoutOptions; - progressCb?: Function; - progressPayload?: any; -} - -export class Stash { - static apply(repo: Repository, index: number, options?: StashApplyOptions): Promise; - static applyInitOptions(opts: StashApplyOptions, version: number): number; - static drop(repo: Repository, index: number): Promise; - static foreach(repo: Repository, callback?: Function): Promise; - static pop(repo: Repository, index: number, options?: StashApplyOptions): Promise; - static save(repo: Repository, stasher: Signature, message: string, flags: number): Promise; -} diff --git a/types/sosuisen__nodegit/status-entry.d.ts b/types/sosuisen__nodegit/status-entry.d.ts deleted file mode 100644 index 59de1a97..00000000 --- a/types/sosuisen__nodegit/status-entry.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { DiffDelta } from './diff-delta'; - -export class StatusEntry { - status(): number; - headToIndex(): DiffDelta; - indexToWorkdir(): DiffDelta; -} diff --git a/types/sosuisen__nodegit/status-file-options.d.ts b/types/sosuisen__nodegit/status-file-options.d.ts deleted file mode 100644 index e3852cf0..00000000 --- a/types/sosuisen__nodegit/status-file-options.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { StatusEntry } from './status-entry'; - -export interface StatusFileOptions { - path?: string; - status?: number; - entry?: StatusEntry; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/status-file.d.ts b/types/sosuisen__nodegit/status-file.d.ts deleted file mode 100644 index b34a0f23..00000000 --- a/types/sosuisen__nodegit/status-file.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { DiffDelta } from './diff-delta'; -import { StatusFileOptions } from './status-file-options'; - -export class StatusFile { - constructor(args: StatusFileOptions); - headToIndex(): DiffDelta; - indexToWorkdir(): DiffDelta; - inIndex(): boolean; - inWorkingTree(): boolean; - isConflicted(): boolean; - isDeleted(): boolean; - isIgnored(): boolean; - isModified(): boolean; - isNew(): boolean; - isRenamed(): boolean; - isTypechange(): boolean; - path(): string; - status(): string[]; - statusBit(): number; -} diff --git a/types/sosuisen__nodegit/status-list.d.ts b/types/sosuisen__nodegit/status-list.d.ts deleted file mode 100644 index 1b470ceb..00000000 --- a/types/sosuisen__nodegit/status-list.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Repository } from './repository'; -import { DiffPerfdata } from './diff-perf-data'; -import { StatusOptions } from './status-options'; - -export class StatusList { - static create(repo: Repository, opts?: StatusOptions): Promise; - - entrycount(): number; - - free(): void; - getPerfdata(): Promise; -} diff --git a/types/sosuisen__nodegit/status-options.d.ts b/types/sosuisen__nodegit/status-options.d.ts deleted file mode 100644 index f0189706..00000000 --- a/types/sosuisen__nodegit/status-options.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Strarray } from './str-array'; - -export interface StatusOptions { - version?: number; - show?: number; - flags?: number; - pathspec?: Strarray | string | string[]; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/status.d.ts b/types/sosuisen__nodegit/status.d.ts deleted file mode 100644 index 5b657d1c..00000000 --- a/types/sosuisen__nodegit/status.d.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Repository } from './repository'; -import { StatusList } from './status-list'; -import { StatusOptions } from './status-options'; -import { StatusEntry } from './status-entry'; - -export namespace Status { - const enum STATUS { - CURRENT = 0, - INDEX_NEW = 1, - INDEX_MODIFIED = 2, - INDEX_DELETED = 4, - INDEX_RENAMED = 8, - INDEX_TYPECHANGE = 16, - WT_NEW = 128, - WT_MODIFIED = 256, - WT_DELETED = 512, - WT_TYPECHANGE = 1024, - WT_RENAMED = 2048, - WT_UNREADABLE = 4096, - IGNORED = 16384, - CONFLICTED = 32768 - } - - const enum OPT { - INCLUDE_UNTRACKED = 1, - INCLUDE_IGNORED = 2, - INCLUDE_UNMODIFIED = 4, - EXCLUDE_SUBMODULES = 8, - RECURSE_UNTRACKED_DIRS = 16, - DISABLE_PATHSPEC_MATCH = 32, - RECURSE_IGNORED_DIRS = 64, - RENAMES_HEAD_TO_INDEX = 128, - RENAMES_INDEX_TO_WORKDIR = 256, - SORT_CASE_SENSITIVELY = 512, - SORT_CASE_INSENSITIVELY = 1024, - RENAMES_FROM_REWRITES = 2048, - NO_REFRESH = 4096, - UPDATE_INDEX = 8192, - INCLUDE_UNREADABLE = 16384, - INCLUDE_UNREADABLE_AS_UNTRACKED = 32768 - } - - const enum SHOW { - INDEX_AND_WORKDIR = 0, - INDEX_ONLY = 1, - WORKDIR_ONLY = 2 - } -} - -export class Status { - static byIndex(statuslist: StatusList, idx: number): StatusEntry; - static file(repo: Repository, path: string): number; - static foreach(repo: Repository, callback?: Function): Promise; - static foreachExt(repo: Repository, opts?: StatusOptions, callback?: Function): Promise; - static shouldIgnore(ignored: number, repo: Repository, path: string): number; -} diff --git a/types/sosuisen__nodegit/str-array.d.ts b/types/sosuisen__nodegit/str-array.d.ts deleted file mode 100644 index 44f5914b..00000000 --- a/types/sosuisen__nodegit/str-array.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class Strarray { - copy(src: Strarray): number; - - free(): void; - strings: string[]; - count: number; -} diff --git a/types/sosuisen__nodegit/submodule-update-options.d.ts b/types/sosuisen__nodegit/submodule-update-options.d.ts deleted file mode 100644 index 5be827b3..00000000 --- a/types/sosuisen__nodegit/submodule-update-options.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { CheckoutOptions } from './checkout-options'; -import { FetchOptions } from './fetch-options'; - -export interface SubmoduleUpdateOptions { - version?: number; - checkoutOpts?: CheckoutOptions; - fetchOpts?: FetchOptions; - cloneCheckoutStrategy?: number; - [key: string]: any; -} diff --git a/types/sosuisen__nodegit/submodule.d.ts b/types/sosuisen__nodegit/submodule.d.ts deleted file mode 100644 index 4ac5ce3a..00000000 --- a/types/sosuisen__nodegit/submodule.d.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Repository } from './repository'; -import { Buf } from './buf'; -import { Oid } from './oid'; -import { SubmoduleUpdateOptions } from './submodule-update-options'; - -export namespace Submodule { - const enum IGNORE { - UNSPECIFIED = -1, - NONE = 1, - UNTRACKED = 2, - DIRTY = 3, - ALL = 4 - } - - const enum RECURSE { - NO = 0, - YES = 1, - ONDEMAND = 2 - } - - const enum STATUS { - IN_HEAD = 1, - IN_INDEX = 2, - IN_CONFIG = 4, - IN_WD = 8, - INDEX_ADDED = 16, - INDEX_DELETED = 32, - INDEX_MODIFIED = 64, - WD_UNINITIALIZED = 128, - WD_ADDED = 256, - WD_DELETED = 512, - WD_MODIFIED = 1024, - WD_INDEX_MODIFIED = 2048, - WD_WD_MODIFIED = 4096, - WD_UNTRACKED = 8192 - } - - const enum UPDATE { - CHECKOUT = 1, - REBASE = 2, - MERGE = 3, - NONE = 4, - DEFAULT = 0 - } -} - -export class Submodule { - static addSetup(repo: Repository, url: string, path: string, useGitLink: number): Promise; - static foreach(repo: Repository, callback?: Function): Promise; - static lookup(repo: Repository, name: string): Promise; - static resolveUrl(repo: Repository, url: string): Promise; - static setBranch(repo: Repository, name: string, branch: string): number; - static setFetchRecurseSubmodules(repo: Repository, name: string, fetchRecurseSubmodules: number): number; - static setIgnore(repo: Repository, name: string, ignore: number): Promise; - static setUpdate(repo: Repository, name: string, update: number): Promise; - static setUrl(repo: Repository, name: string, url: string): Promise; - static status(repo: Repository, name: string, ignore: number): Promise; - static updateInitOptions(opts: SubmoduleUpdateOptions, version: number): number; - - addFinalize(): Promise; - addToIndex(writeIndex: number): Promise; - branch(): string; - fetchRecurseSubmodules(): number; - - free(): void; - headId(): Oid; - ignore(): number; - indexId(): Oid; - init(overwrite: number): Promise; - location(): Promise; - name(): string; - open(): Promise; - owner(): Repository; - path(): string; - reload(force: number): number; - repoInit(useGitLink: number): Promise; - sync(): Promise; - /** - * Updates a submodule - * - * - */ - update(init: number, options?: SubmoduleUpdateOptions): Promise; - updateStrategy(): number; - url(): string; - wdId(): Oid; -} diff --git a/types/sosuisen__nodegit/tag.d.ts b/types/sosuisen__nodegit/tag.d.ts deleted file mode 100644 index 662e8abc..00000000 --- a/types/sosuisen__nodegit/tag.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Repository } from './repository'; -import { Oid } from './oid'; -import { Object } from './object'; -import { Signature } from './signature'; -import { Strarray } from './str-array'; - -export class Tag { - static annotationCreate(repo: Repository, tagName: string, target: Object, tagger: Signature, message: string): Promise; - static create(repo: Repository, tagName: string, target: Object, tagger: Signature, message: string, force: number): Promise; - static createLightweight(repo: Repository, tagName: string, target: Object, force: number): Promise; - static delete(repo: Repository, tagName: string): Promise; - static list(repo: Repository): Promise; - static listMatch(tagNames: Strarray | string | string[], pattern: string, repo: Repository): number; - /** - * Retrieves the tag pointed to by the oid - * - * - */ - static lookup(repo: Repository, id: string | Oid | Tag): Promise; - static lookupPrefix(repo: Repository, id: Oid, len: number): Promise; - - dup(): Promise; - - free(): void; - id(): Oid; - message(): string; - name(): string; - owner(): Repository; - peel(tagTargetOut: Object): number; - tagger(): Signature; - target(): Promise; - targetId(): Oid; - targetType(): number; -} diff --git a/types/sosuisen__nodegit/time.d.ts b/types/sosuisen__nodegit/time.d.ts deleted file mode 100644 index cb42ea68..00000000 --- a/types/sosuisen__nodegit/time.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export class Time { - time(): number; - offset(): number; -} diff --git a/types/sosuisen__nodegit/transfer-progress.d.ts b/types/sosuisen__nodegit/transfer-progress.d.ts deleted file mode 100644 index 1589d4b6..00000000 --- a/types/sosuisen__nodegit/transfer-progress.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export class TransferProgress { - totalObjects: number; - indexedObjects: number; - receivedObjects: number; - localObjects: number; - totalDeltas: number; - indexedDeltas: number; - receivedBytes: number; -} diff --git a/types/sosuisen__nodegit/transport.d.ts b/types/sosuisen__nodegit/transport.d.ts deleted file mode 100644 index f4f47213..00000000 --- a/types/sosuisen__nodegit/transport.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Remote } from './remote'; -import { Strarray } from './str-array'; -import { Cert } from './cert'; - -export namespace Transport { - const enum FLAGS { - NONE = 0 - } -} - -export class Transport { - static sshWithPaths(owner: Remote, payload: Strarray | string | string[]): Promise; - static unregister(prefix: string): number; - init(version: number): number; - smartCertificateCheck(cert: Cert, valid: number, hostName: string): number; -} diff --git a/types/sosuisen__nodegit/tree-builder.d.ts b/types/sosuisen__nodegit/tree-builder.d.ts deleted file mode 100644 index bd8728e1..00000000 --- a/types/sosuisen__nodegit/tree-builder.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Oid } from './oid'; -import { Repository } from './repository'; -import { Tree } from './tree'; -import { TreeEntry } from './tree-entry'; - -export class Treebuilder { - static create(repo: Repository, source?: Tree): Promise; - clear(): void; - entrycount(): number; - free(): void; - get(filename: string): TreeEntry; - insert(filename: string, id: Oid, filemode: number): Promise; - remove(filename: string): number; - write(): Promise; -} diff --git a/types/sosuisen__nodegit/tree-entry.d.ts b/types/sosuisen__nodegit/tree-entry.d.ts deleted file mode 100644 index a5e68a60..00000000 --- a/types/sosuisen__nodegit/tree-entry.d.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Tree } from './tree'; -import { Oid } from './oid'; -import { Blob } from './blob'; -import { Repository } from './repository'; - -export namespace TreeEntry { - const enum FILEMODE { - UNREADABLE = 0, - TREE = 16384, - BLOB = 33188, - EXECUTABLE = 33261, - LINK = 40960, - COMMIT = 57344 - } -} - -export class TreeEntry { - filemode(): TreeEntry.FILEMODE; - filemodeRaw(): TreeEntry.FILEMODE; - free(): void; - getBlob(): Promise; - getTree(): Promise; - id(): Oid; - isBlob(): boolean; - isFile(): boolean; - isTree(): boolean; - isDirectory(): boolean; - isSubmodule(): boolean; - /** - * Retrieve the SHA for this TreeEntry. - */ - sha(): string; - name(): string; - /** - * Retrieve the SHA for this TreeEntry. Alias for sha - */ - oid(): string; - /** - * Returns the path for this entry. - */ - path(): string; - /** - * Alias for path - */ - toString(): string; - toObject(repo: Repository): Object; - type(): number; -} diff --git a/types/sosuisen__nodegit/tree-update.d.ts b/types/sosuisen__nodegit/tree-update.d.ts deleted file mode 100644 index fde63d06..00000000 --- a/types/sosuisen__nodegit/tree-update.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Oid } from './oid'; - -export class TreeUpdate { - action: number; - filemode: number; - id: Oid; - path: string; -} diff --git a/types/sosuisen__nodegit/tree.d.ts b/types/sosuisen__nodegit/tree.d.ts deleted file mode 100644 index c850ffb4..00000000 --- a/types/sosuisen__nodegit/tree.d.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Oid } from './oid'; -import { TreeEntry } from './tree-entry'; -import { Repository } from './repository'; -import { Object } from './object'; -import { Treebuilder } from './tree-builder'; -import { DiffFile } from './diff-file'; -import { TreeUpdate } from './tree-update'; -import { Diff } from './diff'; - -export namespace Tree { - const enum WALK_MODE { - WALK_PRE = 0, - WALK_POST = 1 - } -} - -export class Tree { - static entryCmp(tree1: TreeEntry, tree2: TreeEntry): number; - static entryDup(dest: TreeEntry, source: TreeEntry): number; - static lookupPrefix(repo: Repository, id: Oid, len: number): Promise; - /** - * Retrieves the tree pointed to by the oid - */ - static lookup(repo: Repository, id: string | Oid | Tree, callback?: Function): Promise; - - entryById(id: Oid): TreeEntry; - _entryByIndex(idx: number): TreeEntry; - /** - * Get an entry by name; if the tree is a directory, the name is the filename. - */ - entryByName(name: string): TreeEntry; - _entryByName(filename: string): TreeEntry; - entryByPath(path: string): Promise; - entryCount(): number; - - free(): void; - id(): Oid; - owner(): Repository; - /** - * Diff two trees - */ - diff(tree: Tree, callback?: Function): Promise; - /** - * Diff two trees with options - */ - diffWithOptions(tree: Tree, options?: Object, callback?: Function): Promise; - /** - * Get an entry at the ith position. - */ - entryByIndex(i: number): TreeEntry; - /** - * Get an entry at a path. Unlike by name, this takes a fully qualified path, like /foo/bar/baz.javascript - */ - getEntry(filePath: string): Promise; - /** - * Return an array of the entries in this tree (excluding its children). - */ - entries(): TreeEntry[]; - /** - * Recursively walk the tree in breadth-first order. Fires an event for each entry. - */ - walk(blobsOnly?: boolean): NodeJS.EventEmitter & { - /** - * Start walking the tree and emitting events. This should be called after event listeners have been attached. - */ - start: () => void; - }; - /** - * Return the path of this tree, like /lib/foo/bar - * - * - */ - path(): string; - /** - * Make builder. This is helpful for modifying trees. - */ - builder(): Treebuilder; - dup(): Promise; - createUpdated(repo: Repository, nUpdates: number, updates: TreeUpdate): Promise; -} diff --git a/types/sosuisen__nodegit/wrapper.d.ts b/types/sosuisen__nodegit/wrapper.d.ts deleted file mode 100644 index 8982280a..00000000 --- a/types/sosuisen__nodegit/wrapper.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class Wrapper { - toBuffer(bufSize: number): Buffer; -}