diff --git a/.gitignore b/.gitignore index 1f8d887..0f64cbe 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ build prism-db *.tgz docs-html +db/ +crash.log +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index 60a3fd7..63dbed2 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,12 @@ # Pluto Encrypted -Is a community maintained project which aims to bring a scalable and future proof storage solution for Wallet SDK on typescript. By using this package you can ensure that this dependency will fit the AtalaPrism wallet SDK contract and provide the SDK with storage finally. - -## Interface -Edge SDK Pluto interface [v4.0.0](https://input-output-hk.github.io/atala-prism-wallet-sdk-ts/interfaces/Domain.Pluto.html) -```typescript - -export interface Pluto { - - storeCredentialMetadata(metadata: Anoncreds.CredentialRequestMeta, linkSecret: Anoncreds.LinkSecret): Promise; - - fetchCredentialMetadata(linkSecretName: string): Promise; - - start(): Promise; - - storePrismDID(did: DID, keyPathIndex: number, privateKey: PrivateKey, privateKeyMetaId: string | null, alias?: string): Promise; - - storePeerDID(did: DID, privateKeys: Array): Promise; - - storeDIDPair(host: DID, receiver: DID, name: string): Promise; - - storeMessage(message: Message): Promise; - - storeMessages(messages: Array): Promise; - - storePrivateKeys(privateKey: PrivateKey, did: DID, keyPathIndex: number, metaId: string | null): Promise; - - storeMediator(mediator: DID, host: DID, routing: DID): Promise; - - storeCredential(credential: Credential): Promise; - - getAllPrismDIDs(): Promise; - - getDIDInfoByDID(did: DID): Promise; - - getDIDInfoByAlias(alias: string): Promise; - - getPrismDIDKeyPathIndex(did: DID): Promise; - - getPrismLastKeyPathIndex(): Promise; - - getAllPeerDIDs(): Promise>; - - getDIDPrivateKeysByDID(did: DID): Promise>; - - getDIDPrivateKeyByID(id: string): Promise; - - getAllDidPairs(): Promise>; - getPairByDID(did: DID): Promise; - - getPairByName(name: string): Promise; - - getAllMessages(): Promise>; - - getAllMessagesByDID(did: DID): Promise>; - - getAllMessagesSent(): Promise>; - - getAllMessagesReceived(): Promise>; - - getAllMessagesSentTo(did: DID): Promise>; - - getAllMessagesReceivedFrom(did: DID): Promise>; - - getAllMessagesOfType(type: string, relatedWithDID?: DID): Promise>; - - getAllMessagesByFromToDID(from: DID, to: DID): Promise>; - - getMessage(id: string): Promise; - - getAllMediators(): Promise>; - - getAllCredentials(): Promise>; - - getLinkSecret(linkSecretName?: string): Promise; - - storeLinkSecret(linkSecret: Anoncreds.LinkSecret, linkSecretName: string): Promise; -} -``` +Is a community maintained project which aims to bring a scalable and future proof storage solution for Wallet SDK on typescript. By using this package you can ensure that this dependency will fit the AtalaPrism wallet SDK contract and provide the SDK with storage finally. We currently support database wrappers for IndexDB, InMemory, LevelDB. We are not going to stop here but ensure that our SDK can be used in any platform and language. -### Documentation & Contribution Guidelines +## Documentation & Contribution Guidelines + The pluto encrypted documentation is always available on all branches [HERE](https://github.com/elribonazo/pluto-encrypted/blob/master/docs/README.md) but we have also deployed an online version of documentation. Go to documentation portal [here](https://atala-community-projects.github.io/pluto-encrypted) @@ -90,7 +14,7 @@ Go to documentation portal [here](https://atala-community-projects.github.io/plu Pull requests are WELCOME!! please check the [Contribution guidelines](https://github.com/elribonazo/pluto-encrypted/blob/master/CONTRIBUTION-GUIDELINES.md) first -### How to use +## How to use We currently provide 3 database storages - InMemory, IndexDB, and LevelDB. These modules are designed to be used with [`@atala/prism-wallet-sdk`](https://github.com/input-output-hk/atala-prism-wallet-sdk-ts) @@ -156,3 +80,13 @@ const pluto = new Pluto(store, apollo) const agent = Agent.initialize({ mediatorDID, pluto, apollo }) ``` + +## Development + +### Tests + +```bash +npm install +npm run build +npm run test +``` diff --git a/package-lock.json b/package-lock.json index 11f6338..a171d9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,11 +12,6 @@ "workspaces": [ "packages/*" ], - "dependencies": { - "patch-package": "^8.0.0", - "postinstall-postinstall": "^2.1.0", - "typedoc-plugin-external-module-map": "^2.0.1" - }, "devDependencies": { "@bndynet/typedoc-theme": "^0.0.1", "@rollup/plugin-commonjs": "^25.0.0", @@ -54,7 +49,9 @@ "jasmine": "^5.1.0", "mock-aws-s3": "^4.0.2", "nx": "^19.3.0", + "patch-package": "^8.0.0", "postcss": "^8.4.31", + "postinstall-postinstall": "^2.1.0", "prettier": "^2.4.1", "rimraf": "^5.0.1", "rollup-plugin-cleanup": "^3.2.1", @@ -74,13 +71,14 @@ "semantic-release-monorepo": "^8.0.2", "sinon": "^16.1.3", "typedoc": "^0.24.8", + "typedoc-plugin-external-module-map": "^2.0.1", "typedoc-plugin-markdown": "^3.15.3", "typedoc-plugin-merge-modules": "^5.1.0", "typedoc-plugin-rename-defaults": "^0.6.5", "typedoc-plugin-superstruct": "^1.0.0", "typedoc-theme-hierarchy": "^4.0.0", "typescript": "^5.1.3", - "vitest": "^1.0.4" + "vitest": "^1.6.0" } }, "node_modules/@ampproject/remapping": { @@ -1837,7 +1835,7 @@ "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, + "devOptional": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1850,7 +1848,7 @@ "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, + "devOptional": true, "engines": { "node": ">= 8" } @@ -1859,7 +1857,7 @@ "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, + "devOptional": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -2271,6 +2269,13 @@ "node": ">=12" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", + "optional": true, + "peer": true + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -3751,6 +3756,28 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/ui": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.6.0.tgz", + "integrity": "sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==", + "optional": true, + "peer": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "fast-glob": "^3.3.2", + "fflate": "^0.8.1", + "flatted": "^3.2.9", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "sirv": "^2.0.4" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.0" + } + }, "node_modules/@vitest/utils": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", @@ -3951,7 +3978,8 @@ "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true }, "node_modules/@yarnpkg/parsers": { "version": "3.0.0-rc.46", @@ -4133,12 +4161,14 @@ "node_modules/ansi-sequence-parser": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", - "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==" + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true }, "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" }, @@ -4364,6 +4394,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, "engines": { "node": ">= 4.0.0" } @@ -4396,7 +4427,8 @@ "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==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base64-arraybuffer-es6": { "version": "0.7.0", @@ -4491,6 +4523,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -4499,6 +4532,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "devOptional": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -4726,6 +4760,7 @@ "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" @@ -4741,6 +4776,7 @@ "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" }, @@ -4782,6 +4818,7 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, "funding": [ { "type": "github", @@ -4845,23 +4882,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/cli-highlight/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/cli-highlight/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -4930,23 +4950,6 @@ "node": ">=12" } }, - "node_modules/cliui/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/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -4960,6 +4963,7 @@ "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" }, @@ -4970,7 +4974,8 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/colorette": { "version": "1.4.0", @@ -5024,7 +5029,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/concurrently": { "version": "8.2.2", @@ -6776,7 +6782,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, + "devOptional": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -6792,7 +6798,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, + "devOptional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -6816,7 +6822,7 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, + "devOptional": true, "dependencies": { "reusify": "^1.0.4" } @@ -6833,6 +6839,13 @@ "node": ">=0.8.0" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "optional": true, + "peer": true + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -6902,6 +6915,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "devOptional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6998,6 +7012,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, "dependencies": { "micromatch": "^4.0.2" } @@ -7123,7 +7138,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "devOptional": true }, "node_modules/follow-redirects": { "version": "1.15.6", @@ -7265,7 +7280,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -7614,7 +7630,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -7688,6 +7705,7 @@ "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" } @@ -7988,6 +8006,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -8181,6 +8200,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, "bin": { "is-docker": "cli.js" }, @@ -8195,7 +8215,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -8228,7 +8248,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, + "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -8305,6 +8325,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "devOptional": true, "engines": { "node": ">=0.12.0" } @@ -8544,6 +8565,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, "dependencies": { "is-docker": "^2.0.0" }, @@ -8915,6 +8937,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz", "integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "isarray": "^2.0.5", @@ -8955,12 +8978,14 @@ "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "dependencies": { "universalify": "^2.0.0" }, @@ -8972,6 +8997,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9044,6 +9070,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, "dependencies": { "graceful-fs": "^4.1.11" } @@ -9398,7 +9425,8 @@ "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true }, "node_modules/magic-string": { "version": "0.30.10", @@ -9566,7 +9594,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 8" } @@ -9575,6 +9603,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "devOptional": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -9644,6 +9673,7 @@ "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -9658,6 +9688,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9849,6 +9880,16 @@ "node": ">=16" } }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -12895,6 +12936,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -12952,6 +12994,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -13226,6 +13269,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "dev": true, "dependencies": { "@yarnpkg/lockfile": "^1.1.0", "chalk": "^4.1.2", @@ -13255,6 +13299,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -13264,6 +13309,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -13279,6 +13325,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -13298,6 +13345,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -13309,6 +13357,7 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" @@ -13325,6 +13374,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -13336,6 +13386,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, "engines": { "node": ">=6" } @@ -13344,6 +13395,7 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -13364,6 +13416,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -13453,6 +13506,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "devOptional": true, "engines": { "node": ">=8.6" }, @@ -13781,6 +13835,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz", "integrity": "sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==", + "dev": true, "hasInstallScript": true }, "node_modules/prelude-ls": { @@ -13963,7 +14018,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -14438,7 +14493,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, + "devOptional": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -14910,7 +14965,7 @@ "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, + "devOptional": true, "funding": [ { "type": "github", @@ -16058,6 +16113,7 @@ "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -16163,6 +16219,7 @@ "version": "0.14.7", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", "jsonc-parser": "^3.2.0", @@ -16398,6 +16455,21 @@ "node": ">=8" } }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "optional": true, + "peer": true, + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/skin-tone": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", @@ -17206,6 +17278,7 @@ "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==", + "devOptional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -17213,6 +17286,16 @@ "node": ">=8.0" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -17440,6 +17523,7 @@ "version": "0.24.8", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "dev": true, "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", @@ -17460,6 +17544,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/typedoc-plugin-external-module-map/-/typedoc-plugin-external-module-map-2.0.1.tgz", "integrity": "sha512-B8GC2SxQdTc7PR7etJ7Ahwv7OJNSB3/S8sfQ46nN8fOgcWw9CqTyl/542ZPemxO2UNRwKgV2vdxttbXV82NIpA==", + "dev": true, "peerDependencies": { "typedoc": ">=0.24 <2.0" } @@ -17533,6 +17618,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, "bin": { "marked": "bin/marked.js" }, @@ -17544,6 +17630,7 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -17713,6 +17800,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, "engines": { "node": ">= 10.0.0" } @@ -18121,12 +18209,14 @@ "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true }, "node_modules/vscode-textmate": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true }, "node_modules/watchpack": { "version": "2.4.1", @@ -18372,6 +18462,23 @@ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "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-cjs": { "name": "wrap-ansi", "version": "7.0.0", @@ -18393,7 +18500,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/ws": { "version": "8.16.0", @@ -18443,6 +18551,7 @@ "version": "2.4.5", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "dev": true, "bin": { "yaml": "bin.mjs" }, @@ -18533,7 +18642,7 @@ }, "packages/encryption": { "name": "@pluto-encrypted/encryption", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "dependencies": { "@noble/ciphers": "^0.4.1", @@ -18576,17 +18685,17 @@ }, "packages/indexdb": { "name": "@pluto-encrypted/indexdb", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "dependencies": { - "@pluto-encrypted/encryption": "2.0.0", - "@pluto-encrypted/shared": "2.0.0", + "@pluto-encrypted/encryption": "2.0.1", + "@pluto-encrypted/shared": "2.0.1", "array-push-at-sort-position": "^4.0.1" }, "devDependencies": { - "@pluto-encrypted/encryption": "2.0.0", - "@pluto-encrypted/shared": "2.0.0", - "@pluto-encrypted/test-suite": "2.0.0", + "@pluto-encrypted/encryption": "2.0.1", + "@pluto-encrypted/shared": "2.0.1", + "@pluto-encrypted/test-suite": "2.0.1", "rxdb": "15.24.0", "uuid": "^9.0.1" }, @@ -18597,17 +18706,17 @@ }, "packages/inmemory": { "name": "@pluto-encrypted/inmemory", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "dependencies": { - "@pluto-encrypted/encryption": "2.0.0", - "@pluto-encrypted/shared": "2.0.0", + "@pluto-encrypted/encryption": "2.0.1", + "@pluto-encrypted/shared": "2.0.1", "array-push-at-sort-position": "^4.0.1" }, "devDependencies": { - "@pluto-encrypted/encryption": "2.0.0", - "@pluto-encrypted/shared": "2.0.0", - "@pluto-encrypted/test-suite": "2.0.0", + "@pluto-encrypted/encryption": "2.0.1", + "@pluto-encrypted/shared": "2.0.1", + "@pluto-encrypted/test-suite": "2.0.1", "rxdb": "15.24.0", "uuid": "^9.0.1" }, @@ -18618,11 +18727,11 @@ }, "packages/leveldb": { "name": "@pluto-encrypted/leveldb", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "dependencies": { - "@pluto-encrypted/encryption": "2.0.0", - "@pluto-encrypted/shared": "2.0.0", + "@pluto-encrypted/encryption": "2.0.1", + "@pluto-encrypted/shared": "2.0.1", "array-push-at-sort-position": "^4.0.1", "level": "^6.0.1", "module-error": "^1.0.2", @@ -18630,9 +18739,9 @@ "pull-stream": "^3.7.0" }, "devDependencies": { - "@pluto-encrypted/encryption": "2.0.0", - "@pluto-encrypted/shared": "2.0.0", - "@pluto-encrypted/test-suite": "2.0.0", + "@pluto-encrypted/encryption": "2.0.1", + "@pluto-encrypted/shared": "2.0.1", + "@pluto-encrypted/test-suite": "2.0.1", "rxdb": "15.24.0", "uuid": "^9.0.1" }, @@ -18643,7 +18752,7 @@ }, "packages/shared": { "name": "@pluto-encrypted/shared", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "devDependencies": { "rxdb": "15.24.0", @@ -18656,7 +18765,7 @@ }, "packages/test-suite": { "name": "@pluto-encrypted/test-suite", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "dependencies": { "@faker-js/faker": "^8.3.1", diff --git a/package.json b/package.json index d8d4e81..84d6d41 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,9 @@ "jasmine": "^5.1.0", "mock-aws-s3": "^4.0.2", "nx": "^19.3.0", + "patch-package": "^8.0.0", "postcss": "^8.4.31", + "postinstall-postinstall": "^2.1.0", "prettier": "^2.4.1", "rimraf": "^5.0.1", "rollup-plugin-cleanup": "^3.2.1", @@ -79,18 +81,14 @@ "semantic-release-monorepo": "^8.0.2", "sinon": "^16.1.3", "typedoc": "^0.24.8", + "typedoc-plugin-external-module-map": "^2.0.1", "typedoc-plugin-markdown": "^3.15.3", "typedoc-plugin-merge-modules": "^5.1.0", "typedoc-plugin-rename-defaults": "^0.6.5", "typedoc-plugin-superstruct": "^1.0.0", "typedoc-theme-hierarchy": "^4.0.0", "typescript": "^5.1.3", - "vitest": "^1.0.4" - }, - "dependencies": { - "patch-package": "^8.0.0", - "postinstall-postinstall": "^2.1.0", - "typedoc-plugin-external-module-map": "^2.0.1" + "vitest": "^1.6.0" }, "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610" } diff --git a/packages/indexdb/tests/init.test.ts b/packages/indexdb/tests/init.test.ts index 67e7905..11f13d3 100644 --- a/packages/indexdb/tests/init.test.ts +++ b/packages/indexdb/tests/init.test.ts @@ -12,7 +12,7 @@ describe("Testing suite", () => { runTestSuite({ describe, it, beforeEach, afterEach }, { - name: 'leveldb', + name: 'indexdb', getStorage() { return IndexDB }, diff --git a/packages/indexdb/tests/setup.ts b/packages/indexdb/tests/setup.ts index 1361d2a..5f8f27b 100644 --- a/packages/indexdb/tests/setup.ts +++ b/packages/indexdb/tests/setup.ts @@ -16,4 +16,5 @@ Object.defineProperty(globalThis, "crypto", { }, }); -Object.assign(global, { TextDecoder, TextEncoder }); +const _TextUtils = JSON.parse(JSON.stringify({ TextDecoder, TextEncoder })) +Object.assign(global, _TextUtils) diff --git a/packages/indexdb/vitest.config.ts b/packages/indexdb/vitest.config.mts similarity index 100% rename from packages/indexdb/vitest.config.ts rename to packages/indexdb/vitest.config.mts diff --git a/packages/inmemory/tests/setup.ts b/packages/inmemory/tests/setup.ts index 164f4a3..eaa588f 100644 --- a/packages/inmemory/tests/setup.ts +++ b/packages/inmemory/tests/setup.ts @@ -15,4 +15,5 @@ Object.defineProperty(globalThis, "crypto", { }, }); -Object.assign(global, { TextDecoder, TextEncoder }); +const _TextUtils = JSON.parse(JSON.stringify({ TextDecoder, TextEncoder })) +Object.assign(global, _TextUtils) diff --git a/packages/inmemory/vitest.config.ts b/packages/inmemory/vitest.config.mts similarity index 100% rename from packages/inmemory/vitest.config.ts rename to packages/inmemory/vitest.config.mts diff --git a/packages/leveldb/package.json b/packages/leveldb/package.json index 6728606..659e54d 100644 --- a/packages/leveldb/package.json +++ b/packages/leveldb/package.json @@ -20,8 +20,8 @@ "clean-packages": "rm -rf node_modules && rm -rf build", "build": "rm -rf build && npx rollup -c rollup/rollup.mjs", "coverage": "npx vitest run --coverage", - "test": " npx vitest --run tests/*.test.ts", - "test:watch": "NODE_ENV=debug vitest tests/*.test.ts", + "test": "vitest run", + "test:watch": "NODE_ENV=debug vitest watch", "test:debug": "NODE_ENV=debug vitest tests/*.test.ts --inspect-brk" }, "repository": { diff --git a/packages/leveldb/src/leveldb/instance.ts b/packages/leveldb/src/leveldb/instance.ts index fc01537..9c28fa7 100644 --- a/packages/leveldb/src/leveldb/instance.ts +++ b/packages/leveldb/src/leveldb/instance.ts @@ -43,7 +43,7 @@ import type { import { boundGE, boundGT, boundLE, boundLT, compareDocsWithIndex } from '@pluto-encrypted/shared' export function getIndexName(index: string[]): string { - return index.join(','); + return `[${index.join('+')}]`; } export class RxStorageIntanceLevelDB implements RxStorageInstance< @@ -166,57 +166,87 @@ export class RxStorageIntanceLevelDB implements RxStorageInstance< ); } + console.log('queryPlan', queryPlan) + // this makes the index .. which is wrong!? + // NOTE: it's wrong + const queryPlanFields: string[] = queryPlan.index; const mustManuallyResort = !queryPlan.sortSatisfiedByIndex; const index: string[] | undefined = queryPlanFields; + const _index = ['key'] + console.log({ _index }) + const lowerBound: any[] = queryPlan.startKeys; const lowerBoundString = getStartIndexStringFromLowerBound( this.schema, - index, + _index, // index, lowerBound ); const upperBound: any[] = queryPlan.endKeys; - const upperBoundString = getStartIndexStringFromUpperBound( this.schema, - index, + _index, // index, upperBound ); - const indexName = getIndexName(index); - const docsWithIndex = await this.internals.getIndex(indexName) + + // HACK: getIndex(index) is doing the wrong thing ... so mutate the index (after upper/lower bound stuff) + const indexName = getIndexName([this.collectionName, 'key']) + console.log('index (wrong)', index) + console.log('getIndexName =>', indexName) + + // const indexName = getIndexName(index); + // // => '_meta.lwt,key' + // QUESTION: this doesn't seem to map to any of the indexes being entered? + // with setIndex + const docsWithIndex = (await this.internals.getIndex(indexName)) + + console.log({ docsWithIndex }) + console.log({ lowerBoundString, upperBoundString }) let indexOfLower = (queryPlan.inclusiveStart ? boundGE : boundGT)( - docsWithIndex, + // docsWithIndex, + // HACK: ecchh + docsWithIndex.map(d => { return { indexString: d } }), { indexString: lowerBoundString } as any, compareDocsWithIndex + // NOTE: this does comparisons like "a.indexString < b.indexString" + // QUESTION: Are we expecting docsWithIndex to have an indexString attribute? ); const indexOfUpper = (queryPlan.inclusiveEnd ? boundLE : boundLT)( - docsWithIndex, + // docsWithIndex, + // HACK: ecchh + docsWithIndex.map(d => { return { indexString: d } }), { indexString: upperBoundString } as any, compareDocsWithIndex ); + console.log({ indexOfLower, indexOfUpper }) + // { indexOfLower: 0, indexOfUpper: -1 } // QUESTION: what does -1 encode here? let rows: RxDocumentData[] = []; let done = false; while (!done) { const currentRow = docsWithIndex[indexOfLower]; + console.log({ currentRow }) if ( !currentRow || indexOfLower > indexOfUpper ) { + console.log('break') break; } const [currentDoc] = await this.findDocumentsById([currentRow], false) + console.log({ currentDoc }) if (currentDoc && (!queryMatcher || queryMatcher(currentDoc))) { + console.log('match!') rows.push(currentDoc); } @@ -546,4 +576,4 @@ export class RxStorageIntanceLevelDB implements RxStorageInstance< // /* istanbul ignore next */ // async resolveConflictResultionTask(): Promise { // await Promise.resolve() -// } \ No newline at end of file +// } diff --git a/packages/leveldb/src/leveldb/internal.ts b/packages/leveldb/src/leveldb/internal.ts index 92c7668..fbe6d3b 100644 --- a/packages/leveldb/src/leveldb/internal.ts +++ b/packages/leveldb/src/leveldb/internal.ts @@ -44,9 +44,9 @@ export class LevelDBInternal implements LevelDBStorageInternals row && !Array.isArray(row.value)), + pull.filter(row => row && !row.value.match(/^\[.*\]$/)), pull.map(row => { - docsInDbMap.set(row.key, row.value) + docsInDbMap.set(row.key, JSON.parse(row.value)) return row }), pull.collectAsPromise() @@ -70,6 +70,7 @@ export class LevelDBInternal implements LevelDBStorageInternals { + console.log('getIndex', key) const db = await this.getInstance() return db.get(key) .then(result => result ? JSON.parse(result) : []) @@ -128,6 +129,20 @@ export class LevelDBInternal implements LevelDBStorageInternals((resolve, reject) => { db.put(key, JSON.stringify(ids), (err) => { diff --git a/packages/leveldb/tests/basic.test.ts b/packages/leveldb/tests/basic.test.ts new file mode 100644 index 0000000..7b276c9 --- /dev/null +++ b/packages/leveldb/tests/basic.test.ts @@ -0,0 +1,58 @@ +import "./setup"; + +import fs from 'fs'; +import { createRxDatabase } from 'rxdb' +import { describe, it } from 'vitest'; + +import { createLevelDBStorage } from '../src' + +function clean () { + if (fs.existsSync("./db1")) fs.rmdirSync("./db1", { recursive: true }) + if (fs.existsSync("./db2")) fs.rmdirSync("./db2", { recursive: true }) +} + +describe("Basic tests", () => { + + it('should be able to instanciate multiple databases in the same thread', async ({ expect }) => { + clean() + + const collections = { + todo: { + schema: { + version: 0, + primaryKey: 'id', + type: 'object', + properties: { + id: { type: 'string', maxLength: 100 }, + name: { type: 'string' }, + }, + required: ['id', 'name'] + } + } + } + + const level1 = createLevelDBStorage({ dbPath: "./db1" }) + const db1 = await createRxDatabase({ + name: 'level-1-db', + storage: level1, + password: 'password-1' + }) + await db1.addCollections(collections) + await db1.todo.insert({ id: '1', name: 'milk' }) + const record1 = await db1.todo.findOne('1').exec() + expect(record1._data.name).toBe('milk') + + const level2 = createLevelDBStorage({ dbPath: "./db2" }) + const db2 = await createRxDatabase({ + name: 'level-2-db', + storage: level2, + password: 'password-2' + }) + await db2.addCollections(collections) + await db2.todo.insert({ id: '2', name: 'potatoes' }) + const record2 = await db2.todo.findOne('2').exec() + expect(record2._data.name).toBe('potatoes') + + clean() + }) +}) diff --git a/packages/leveldb/tests/init.test.ts b/packages/leveldb/tests/init.test.ts index 3a5c59f..b263528 100644 --- a/packages/leveldb/tests/init.test.ts +++ b/packages/leveldb/tests/init.test.ts @@ -1,10 +1,7 @@ import "./setup"; - import { describe, it, beforeEach, afterEach } from 'vitest'; import { runTestSuite } from '@pluto-encrypted/test-suite'; - - import { createLevelDBStorage } from '../src' describe("Testing suite", () => { diff --git a/packages/leveldb/tests/setup.ts b/packages/leveldb/tests/setup.ts index 164f4a3..5f8f27b 100644 --- a/packages/leveldb/tests/setup.ts +++ b/packages/leveldb/tests/setup.ts @@ -1,5 +1,6 @@ import "fake-indexeddb/auto"; import { TextEncoder, TextDecoder } from "util"; + import { addRxPlugin } from "rxdb"; import { RxDBDevModePlugin } from "rxdb/plugins/dev-mode"; import nodeCrypto from "crypto"; @@ -15,4 +16,5 @@ Object.defineProperty(globalThis, "crypto", { }, }); -Object.assign(global, { TextDecoder, TextEncoder }); +const _TextUtils = JSON.parse(JSON.stringify({ TextDecoder, TextEncoder })) +Object.assign(global, _TextUtils) diff --git a/packages/leveldb/vitest.config.ts b/packages/leveldb/vitest.config.mts similarity index 82% rename from packages/leveldb/vitest.config.ts rename to packages/leveldb/vitest.config.mts index 3165e68..6df256a 100644 --- a/packages/leveldb/vitest.config.ts +++ b/packages/leveldb/vitest.config.mts @@ -9,7 +9,13 @@ export default defineConfig({ terserOptions: { format: { comments: 'all' } }, }, test: { - reporters: ['verbose'], // or 'verbose' + include: [ + 'tests/*.test.ts' + ], + reporters: [ + 'verbose', + // 'tap-flat' + ], coverage: { provider: 'istanbul', reporter: isCI ? ['json-summary'] : ['json-summary', "html"], @@ -23,5 +29,5 @@ export default defineConfig({ 'src/**/*', ], }, - } + }, }) diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 5f2843b..08d6df6 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -38,6 +38,8 @@ export function compareDocsWithIndex( a: DocWithIndexString, b: DocWithIndexString ): 1 | 0 | -1 { + if (a.indexString === undefined) throw Error(`missing indexString on ${a}`) + if (b.indexString === undefined) throw Error(`missing indexString on ${b}`) if (a.indexString < b.indexString) { return -1 } else if (a.indexString === b.indexString) { diff --git a/packages/test-suite/src/helper/index.ts b/packages/test-suite/src/helper/index.ts index e6353bf..ff57730 100644 --- a/packages/test-suite/src/helper/index.ts +++ b/packages/test-suite/src/helper/index.ts @@ -8,7 +8,6 @@ import type { RxDocumentData, RxJsonSchema, RxStorage, - RxStorageInstance, } from 'rxdb' import { createRxDatabase, @@ -18,6 +17,7 @@ import { getPrimaryFieldOfPrimaryKey, getQueryMatcher, getQueryPlan, + // NOTE: this is making a weird queryPlan getSortComparator, lastOfArray, newRxError, @@ -79,6 +79,16 @@ export function prepareQuery(schema, mutateableQuery) { * Store the query plan together with the * prepared query to save performance. */ + console.log('prepareQueryPlan', schema, mutateableQuery) + // NOTE: schema.indexes + // => [ [ '_deleted', 'key' ], [ '_meta.lwt', 'key' ] ] + // QUESTION: these indexes lead directly to the query... + // which then fails find anything with the _meta.lwt,key index .... + // which means we get no results + // ... + // WHY is there this misalignment between setIndex and using indexes + // to look results up? + const queryPlan = getQueryPlan(schema, mutateableQuery) return { query: mutateableQuery, @@ -240,29 +250,19 @@ export function testCorrectQueries( testStorage: RxTestStorage, input: TestCorrectQueriesInput ) { - const { it, describe, beforeEach, afterEach } = suite - let storage: RxStorage - let storageInstance: RxStorageInstance | undefined + const { it, describe } = suite + // let storage: RxStorage + // let storageInstance: RxStorageInstance | undefined describe(`Testing - ${input.testTitle}`, () => { - beforeEach(async () => { - storage = await testStorage.getStorage() - }) - - afterEach(async () => { - if (storageInstance) { - await storageInstance.cleanup(Infinity) - await storageInstance.close() - } - }) - if (input.notRunIfTrue && input.notRunIfTrue()) { return } - it(input.testTitle, async ({ expect }) => { + it(input.testTitle, async () => { const schema = fillWithDefaultSettings(clone(input.schema)); const primaryPath = getPrimaryFieldOfPrimaryKey(schema.primaryKey); + const storage = await testStorage.getStorage() const storageInstance = await storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), @@ -372,6 +372,7 @@ export function testCorrectQueries( } // Test output of RxStorageInstance.query(); + // TODO: queries arent returning anything const resultFromStorage = await storageInstance.query(preparedQuery); const resultIds = resultFromStorage.documents.map(d => (d as any)[primaryPath]); try { @@ -421,6 +422,7 @@ export function testCorrectQueries( } await Promise.all([ database.remove(), + storageInstance.cleanup(Infinity), storageInstance.close() ]); }) diff --git a/packages/test-suite/src/index.ts b/packages/test-suite/src/index.ts index ad064bb..0f0c14b 100644 --- a/packages/test-suite/src/index.ts +++ b/packages/test-suite/src/index.ts @@ -9,9 +9,7 @@ import type { RxDocumentData, RxDocumentWriteData, RxJsonSchema, - RxStorage, RxStorageBulkWriteResponse, - RxStorageInstance, } from 'rxdb' import { clone, @@ -70,30 +68,18 @@ import { schemaObjects } from 'rxdb/plugins/test-utils' -let storage: RxStorage -let storageInstance: RxStorageInstance | undefined - export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void { - const { describe, it, beforeEach, afterEach } = suite - describe('RxStorageInstance', () => { - beforeEach(async () => { - storage = await testStorage.getStorage() - }) - - afterEach(async () => { - if (storageInstance) { - await storageInstance.cleanup(Infinity) - storageInstance = undefined; - } - }) + const { describe, it } = suite - describe('creation', () => { + // tests out the storage module + describe('RxStorageInstance', () => { + describe('creation (single instance)', () => { it('open many instances on the same database name', async () => { const databaseName = randomCouchString(12) const amount = 20 for (let i = 0; i < amount; i++) { - const storageInstance = await testStorage.getStorage().createStorageInstance({ + const _storageInstance = await testStorage.getStorage().createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName, collectionName: randomCouchString(12), @@ -104,15 +90,16 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void password: randomCouchString(24) }) - await storageInstance.cleanup(Infinity) - await storageInstance.close() + await _storageInstance.cleanup(Infinity) + await _storageInstance.close() } }) it('open and close', async ({ expect }) => { const collectionName = randomCouchString(12) const databaseName = randomCouchString(12) - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName, collectionName, @@ -124,13 +111,16 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void }) expect(storageInstance.collectionName).toBe(collectionName) expect(storageInstance.databaseName).toBe(databaseName) - }) + await storageInstance.cleanup(Infinity) + // await storageInstance.close() + }) }) describe('.bulkWrite()', () => { it('should write the document', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -159,10 +149,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void expect(writeResponse.error).toStrictEqual([]) const first = writeResponse.success.at(0); expect(docData).toStrictEqual(first) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) it('should error on conflict', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -195,6 +189,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void }], testContext ) + expect(writeResponse.success).toStrictEqual([]) expect(writeResponse.error.at(0)).not.toBe(undefined) const first = writeResponse.error.at(0)! @@ -217,10 +212,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void * These fields must never be leaked to 409 conflict errors */ expect(Object.keys((first as any).documentInDb).sort()).toStrictEqual(Object.keys(writeData).sort()) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) it('when inserting the same document at the same time, the first call must succeed while the second has a conflict', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -262,10 +261,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void expect(first.error).toStrictEqual([]) expect(first.success.at(0)!.value).toBe('first') expect(second.error.at(0)!.status).toBe(409) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) it('should not find the deleted document when findDocumentsById(false)', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -339,13 +342,17 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const foundDoc = await storageInstance.findDocumentsById([pkey], false) expect(foundDoc).toStrictEqual([]) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) it('should be able to unset a property', async ({ expect }) => { const schema = getTestDataSchema() schema.required = ['key'] - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -354,7 +361,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void multiInstance: true, devMode: false }) - const docId = 'foobar' + const docId = randomString(10) const insertData: RxDocumentWriteData = { key: docId, value: 'barfoo1', @@ -367,17 +374,20 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } const writeResponse = await storageInstance.bulkWrite( [{ - document: insertData + document: clone(insertData) }], testContext ) - expect(writeResponse.success.at(0)).not.toBe(undefined) - const insertResponse = writeResponse.success.at(0) + + expect(writeResponse.error).toStrictEqual([]) + const insertResponse = writeResponse.success.at(0); + expect(insertData).toStrictEqual(insertResponse) + const insertDataAfterWrite: RxDocumentData = Object.assign( {}, insertResponse, { - _rev: insertResponse._rev + _rev: insertResponse!._rev } ) const updateResponse = await storageInstance.bulkWrite( @@ -390,27 +400,35 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void _rev: EXAMPLE_REVISION_2, _meta: { lwt: now(), - } } }], testContext ) expect(updateResponse.success.at(0)).not.toBe(undefined) + expect(updateResponse.error).toStrictEqual([]) const updateResponseDoc = updateResponse.success.at(0)! + // @ts-expect-error typescript :D delete (updateResponseDoc)._deleted + // @ts-expect-error typescript :D delete (updateResponseDoc)._rev + // @ts-expect-error typescript :D delete (updateResponseDoc)._meta + expect(updateResponseDoc).toStrictEqual({ key: docId, _attachments: {} }) + + await storageInstance.cleanup(Infinity) }) it('should be able to do a write where only _meta fields are changed', async ({ expect }) => { const databaseInstanceToken = randomCouchString(10) - storageInstance = await storage.createStorageInstance({ + + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken, databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -480,11 +498,15 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const viaStorage = await storageInstance.findDocumentsById([key], true) const viaStorageDoc = ensureNotFalsy(viaStorage.at(0)) expect(parseRevision(viaStorageDoc._rev).height).toBe(3) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) - it('should be able to create another instance after a write', async () => { + it('should be able to create another instance after a write', async ({ expect }) => { const databaseName = randomCouchString(12) - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName, collectionName: randomCouchString(12), @@ -493,9 +515,13 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void multiInstance: true, devMode: false }) + + const pkey = randomCouchString(12) + const value1 = 'barfoo1' + const docData: RxDocumentWriteData = { - key: 'foobar', - value: 'barfoo1', + key: pkey, + value: value1, _attachments: {}, _deleted: false, _rev: EXAMPLE_REVISION_1, @@ -503,13 +529,20 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void lwt: now() } } - await storageInstance.bulkWrite( + + const writeResponse = await storageInstance.bulkWrite( [{ document: clone(docData) }], testContext ) - const storageInstance2 = await storage.createStorageInstance({ + + expect(writeResponse.error).toStrictEqual([]) + const first = writeResponse.success.at(0); + expect(docData).toStrictEqual(first) + + + const storageInstance2 = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName, collectionName: randomCouchString(12), @@ -533,10 +566,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void await Promise.all([ storageInstance2.cleanup(Infinity).then(async () => { await storageInstance2.close() }) ]) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) it('should be able to jump more then 1 revision height in a single write operation', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -586,6 +623,9 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const docFromDb = getDocFromDb.at(0)! expect(docFromDb._rev).toEqual(EXAMPLE_REVISION_4) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) it('must be able create multiple storage instances on the same database and write documents', async () => { @@ -598,7 +638,8 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void new Array(collectionsAmount) .fill(0) .map(async () => { - const storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken, databaseName, collectionName: randomCouchString(12), @@ -627,11 +668,15 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void return storageInstance }) ) + // TODO: do we need to tidy up and close these instances? + // await storageInstance.cleanup(Infinity) + // await storageInstance.close() }, { timeout: 200000 }) // Some storages had problems storing non-utf-8 chars like "é" it('write and read with umlauts', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -669,7 +714,8 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const docFromDb = getDocFromDb.at(0) - expect(docFromDb.value).toBe('value' + umlauts) + // TODO: linter doesnt like this line + if (docFromDb) expect(docFromDb.value).toBe('value' + umlauts) const pkey2 = 'foobar2' + umlauts // store another doc @@ -692,12 +738,16 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const getDocFromDb2 = await storageInstance.findDocumentsById([docData2.key], false) expect(getDocFromDb2.at(0)).not.toBe(undefined) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) }) describe('.getSortComparator()', () => { it('should sort in the correct order', async ({ expect }) => { - storageInstance = await storage.createStorageInstance<{ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance<{ _id: string age: number }>({ @@ -749,9 +799,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void // should sort in the correct order expect([doc1, doc2]).toStrictEqual([doc1, doc2].sort(comparator)) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) + it('should still sort in correct order when docs do not match the selector', async ({ expect }) => { - const storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -797,9 +852,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void ) expect(result).toStrictEqual(-1) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) + it('should work with a more complex query', async ({ expect }) => { - const storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -853,12 +913,16 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void ) expect(result).toStrictEqual(-1) + + await storageInstance.cleanup(Infinity) + // await storageInstance.close() }) }) describe('.getQueryMatcher()', () => { it('should match the right docs', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -894,11 +958,8 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void assert.strictEqual(matcher(doc1), false); assert.strictEqual(matcher(doc2), true); - storageInstance.remove(); - }) - it('should match the nested document', ({ expect }) => { const schema = getNestedDocSchema() - const query: FilledMangoQuery = { + const query2: FilledMangoQuery = { selector: { 'nes.ted': { $eq: 'barfoo' @@ -912,7 +973,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const queryMatcher = getQueryMatcher( schema, - normalizeMangoQuery(schema, query) + normalizeMangoQuery(schema, query2) ) const notMatchingDoc = { @@ -942,13 +1003,19 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void expect(queryMatcher(notMatchingDoc)).toStrictEqual(false) expect(queryMatcher(matchingDoc)).toStrictEqual(true) + + await storageInstance.cleanup(Infinity) + // storageInstance.remove(); + // await storageInstance.close() }) }) - describe('.query()', () => { - it('should find all documents', async ({ expect }) => { - storageInstance = await storage.createStorageInstance<{ key: string, value: string }>({ + describe('.query()', () => { + // TODO: this test is failing with leveldb + it.only('should find all documents', async ({ expect }) => { + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance<{ key: string, value: string }>({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -958,41 +1025,41 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void devMode: false }) - const writeData = { - key: 'foobar', - value: 'barfoo', - _deleted: false, - _attachments: {}, - _rev: EXAMPLE_REVISION_1, - _meta: { - lwt: now() + async function writeDoc (value) { + const pkey = value.concat(randomCouchString(12)) + + const writeData = { + key: pkey, + value, + _deleted: false, + _attachments: {}, + _rev: EXAMPLE_REVISION_1, + _meta: { + lwt: now() + } } - } - await storageInstance.bulkWrite( - [{ - document: writeData - }], - testContext - ) + const writeResponse = await storageInstance.bulkWrite( + [{ + document: clone(writeData) + }], + testContext + ) - const writeData2 = { - key: 'foobar2', - value: 'barfoo2', - _deleted: false, - _attachments: {}, - _rev: EXAMPLE_REVISION_1, - _meta: { - lwt: now() - } + expect(writeResponse.error).toStrictEqual([]) + const first = writeResponse.success.at(0); + expect(writeData).toStrictEqual(first) + + return clone(writeData) } - await storageInstance.bulkWrite( - [{ - document: writeData2 - }], - testContext - ) + const value1 = '1barfoo' + const value2 = '2barfoo' + + await writeDoc(value1) + await writeDoc(value2) + + // TODO: this query is not returning any documents with leveldb const preparedQuery = prepareQuery( storageInstance.schema, { @@ -1003,24 +1070,21 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void skip: 0 } ) + const allDocs = await storageInstance.query(preparedQuery) - const first = allDocs.documents[0] + expect(allDocs.documents).toHaveLength(2) + const first = allDocs.documents.at(0) expect(first).not.toBe(undefined) - expect(first.value).toBe('barfoo') + expect(first!.value).toBe(value1) - await storageInstance.bulkWrite( - [{ - document: { - ...writeData2, - _deleted: true - } - }], - testContext - ) + await storageInstance.cleanup(Infinity) }) + + // TODO: tests failing because the query isnt returning any documents with leveldb it('should sort in the correct order', async ({ expect }) => { - storageInstance = await storage.createStorageInstance<{ key: string, value: string }>({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance<{ key: string, value: string }>({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -1030,7 +1094,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void devMode: false }) - await storageInstance.bulkWrite([ + const writeResponse = await storageInstance.bulkWrite([ { document: getWriteData({ value: 'a' }) }, @@ -1042,6 +1106,8 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ], testContext) + expect(writeResponse.error).toStrictEqual([]) + const preparedQuery = prepareQuery( storageInstance.schema, { @@ -1054,11 +1120,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void ) const allDocs = await storageInstance.query(preparedQuery) - expect(allDocs.documents.length).toBe(3) - expect(allDocs.documents[0].value).toBe('c') - expect(allDocs.documents[1].value).toBe('b') - expect(allDocs.documents[2].value).toBe('a') + expect(allDocs.documents).toHaveLength(3) + expect(allDocs!.documents[0]!.value).toBe('c') + expect(allDocs!.documents[1]!.value).toBe('b') + expect(allDocs!.documents[2]!.value).toBe('a') + + await storageInstance.cleanup(Infinity) }) + it('should have the same deterministic order of .query() and .getSortComparator()', async ({ expect }) => { const schema: RxJsonSchema> = fillWithDefaultSettings({ version: 0, @@ -1102,7 +1171,9 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void 'random' ] }) - storageInstance = await storage.createStorageInstance({ + + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -1152,6 +1223,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const docsViaSort = shuffleArray(docs).sort(sortComparator) expect(docsViaQuery).toStrictEqual(docsViaSort) } + const queries: Array> = [ { selector: {}, @@ -1193,10 +1265,14 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void for (const query of queries) { await testQuery(query) } + + await storageInstance.cleanup(Infinity) }) + it('should be able to search over a nested object', async ({ expect }) => { const schema = getNestedDocSchema() - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -1243,10 +1319,13 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const results = await storageInstance.query(preparedQuery) expect(results.documents.length).toBe(1) + + await storageInstance.cleanup(Infinity) }) it('querying many documents should work', async ({ expect }) => { const schema = getTestDataSchema() - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -1283,13 +1362,17 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void const results = await storageInstance.query(preparedQuery) expect(results.documents.length).toBe(amount) + + await storageInstance.cleanup(Infinity) }) }) + // TODO: tests failing as the query isnt returning any documents describe('.count()', () => { it('should count the correct amount', async ({ expect }) => { const schema = getTestDataSchema() - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -1298,8 +1381,9 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void multiInstance: true, devMode: false }) + const preparedQueryAll = prepareQuery( - schema, + storageInstance.schema, { selector: {}, sort: [ @@ -1309,22 +1393,36 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ) async function ensureCountIs(nr: number): Promise { - const result = await storageInstance!.count(preparedQueryAll) + // TODO: this query is not returning any documents + const result = await storageInstance.count(preparedQueryAll) expect(result.count).toBe(nr) } - await ensureCountIs(0) - await storageInstance.bulkWrite([{ document: getWriteData() }], testContext) - await ensureCountIs(1) + async function writeDoc () { + const docData = getWriteData() + const writeResponse = await storageInstance.bulkWrite([{ document: clone(docData) }], testContext) + console.log(writeResponse) + + expect(writeResponse.error).toStrictEqual([]) + const first = writeResponse.success.at(0); + expect(docData).toStrictEqual(first) + } - const writeData = getWriteData() - await storageInstance.bulkWrite([{ document: writeData }], testContext) + await ensureCountIs(0) + await writeDoc() + await ensureCountIs(1) + await writeDoc() await ensureCountIs(2) + + await storageInstance.cleanup(Infinity) }) }) + + describe('.findDocumentsById()', () => { it('should find the documents', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -1334,7 +1432,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void devMode: false }) - const pkey = 'foobar' + const pkey = randomCouchString(12) const docData = { key: pkey, value: 'barfoo', @@ -1345,17 +1443,25 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void lwt: now() } } - await storageInstance.bulkWrite( + + const writeResponse = await storageInstance.bulkWrite( [{ - document: docData + document: clone(docData) }], testContext ) - const found = await storageInstance.findDocumentsById(['foobar'], false) - const foundDoc = found.at(0) + expect(writeResponse.error).toStrictEqual([]) + const first = writeResponse.success.at(0); + expect(docData).toStrictEqual(first) + + const found = await storageInstance.findDocumentsById([pkey], false) + expect(found).toHaveLength(1) + const foundDoc = found.at(0) expect(foundDoc).toStrictEqual(docData) + + await storageInstance.cleanup(Infinity) }) /** @@ -1365,7 +1471,8 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void * has to workaround any problems with that. */ it('should be able to insert and fetch many documents', async ({ expect }) => { - storageInstance = await storage.createStorageInstance({ + const _storage = await testStorage.getStorage() + const storageInstance = await _storage.createStorageInstance({ databaseInstanceToken: randomCouchString(10), databaseName: randomCouchString(12), collectionName: randomCouchString(12), @@ -1528,6 +1635,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries(suite, testStorage, { testTitle: '$lt/$lte', data: [ @@ -1553,6 +1661,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries(suite, testStorage, { testTitle: '$lt/$lte', data: [ @@ -1656,6 +1765,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries(suite, testStorage, { testTitle: 'nested properties', data: [ @@ -1701,6 +1811,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries(suite, testStorage, { testTitle: '$or', data: [ @@ -1791,6 +1902,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries(suite, testStorage, { testTitle: '$in', data: [ @@ -1856,6 +1968,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries(suite, testStorage, { testTitle: '$elemMatch/$size', data: [ @@ -2224,6 +2337,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + /** * @link https://github.com/pubkey/rxdb/issues/5273 */ @@ -2325,6 +2439,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries(suite, testStorage, { testTitle: '$type', data: [ @@ -2390,6 +2505,7 @@ export function runTestSuite(suite: TestSuite, testStorage: RxTestStorage): void } ] }) + testCorrectQueries<{ _id: string name: string