From 6bfaa8814f6e2cb57e2b507eee39eb26d0c2fd7f Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Wed, 12 Jul 2023 11:29:08 +1000 Subject: [PATCH 01/35] WIP: working towards full codecov --- package-lock.json | 189 +++++++++- package.json | 9 +- src/common/common.mock.ts | 53 ++- src/common/common.test.ts | 651 +++++++++++++++++++++++++++++++++- src/common/common.ts | 367 +++++++++++++++++-- src/parser/contexts/index.ts | 27 ++ src/parser/contexts/inrupt.ts | 149 ++++++++ src/parser/contexts/vc.ts | 275 ++++++++++++++ src/parser/jsonld.test.ts | 187 ++++++++++ src/parser/jsonld.ts | 146 ++++++++ 10 files changed, 2007 insertions(+), 46 deletions(-) create mode 100644 src/parser/contexts/index.ts create mode 100644 src/parser/contexts/inrupt.ts create mode 100644 src/parser/contexts/vc.ts create mode 100644 src/parser/jsonld.test.ts create mode 100644 src/parser/jsonld.ts diff --git a/package-lock.json b/package-lock.json index 3a12a24d..f45abd82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,11 @@ "license": "MIT", "dependencies": { "@inrupt/solid-client": "^1.25.2", - "@inrupt/universal-fetch": "^1.0.1" + "@inrupt/universal-fetch": "^1.0.1", + "content-type": "^1.0.5", + "event-emitter-promisify": "^1.1.0", + "jsonld-streaming-serializer": "^2.1.0", + "n3": "^1.17.0" }, "devDependencies": { "@inrupt/eslint-config-lib": "^2.0.0", @@ -21,8 +25,10 @@ "@rdfjs/dataset": "2.0.1", "@rdfjs/types": "^1.1.0", "@rushstack/eslint-patch": "^1.1.4", + "@types/content-type": "^1.1.5", "@types/dotenv-flow": "^3.1.1", "@types/jest": "^29.2.2", + "@types/n3": "^1.16.0", "@types/node": "^20.1.2", "@types/rdfjs__dataset": "2.0.3", "dotenv-flow": "^3.2.0", @@ -30,6 +36,7 @@ "jest": "^29.3.0", "jest-environment-jsdom": "^29.3.0", "prettier": "2.8.8", + "rdf-isomorphic": "^1.3.1", "rollup": "^3.1.0", "rollup-plugin-typescript2": "^0.35.0", "ts-jest": "^29.0.3", @@ -1711,6 +1718,12 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/content-type": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.5.tgz", + "integrity": "sha512-dgMN+syt1xb7Hk8LU6AODOfPlvz5z1CbXpPuJE5ZrX9STfBOIXF09pEB8N7a97WT9dbngt3ksDCm6GW6yMrxfQ==", + "dev": true + }, "node_modules/@types/dotenv-flow": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@types/dotenv-flow/-/dotenv-flow-3.2.0.tgz", @@ -1806,6 +1819,16 @@ "@types/lodash": "*" } }, + "node_modules/@types/n3": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@types/n3/-/n3-1.16.0.tgz", + "integrity": "sha512-g/67NVSihmIoIZT3/J462NhJrmpCw+5WUkkKqpCE9YxNEWzBwKavGPP+RUmG6DIm5GrW4GPunuxLJ0Yn/GgNjQ==", + "dev": true, + "dependencies": { + "@rdfjs/types": "^1.1.0", + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.3.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", @@ -2946,7 +2969,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -4061,6 +4083,11 @@ "node": ">= 0.6" } }, + "node_modules/event-emitter-promisify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/event-emitter-promisify/-/event-emitter-promisify-1.1.0.tgz", + "integrity": "sha512-uyHG8gjwYGDlKoo0Txtx/u1HI1ubj0FK0rVqI4O0s1EymQm4iAEMbrS5B+XFlSaS8SZ3xzoKX+YHRZk8Nk/bXg==" + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -4854,6 +4881,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -6218,6 +6255,18 @@ "readable-stream": "^4.0.0" } }, + "node_modules/jsonld-streaming-serializer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jsonld-streaming-serializer/-/jsonld-streaming-serializer-2.1.0.tgz", + "integrity": "sha512-COHdLoeMTnrqHMoFhN3PoAwqnrKrpPC7/ACb0WbELYvt+HSOIFN3v4IJP7fOtLNQ4GeaeYkvbeWJ7Jo4EjxMDw==", + "dependencies": { + "@rdfjs/types": "*", + "@types/readable-stream": "^2.3.13", + "buffer": "^6.0.3", + "jsonld-context-parser": "^2.0.0", + "readable-stream": "^4.0.0" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -6448,6 +6497,12 @@ "node": ">=6" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6488,9 +6543,9 @@ "dev": true }, "node_modules/n3": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/n3/-/n3-1.16.3.tgz", - "integrity": "sha512-9caLSZuMW1kdlPxEN4ka6E4E8a5QKoZ2emxpW+zHMofI+Bo92nJhN//wNub15S5T9I4c6saEqdGEu+YXJqMZVA==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/n3/-/n3-1.17.0.tgz", + "integrity": "sha512-dYdkyUM4tMWHSEf9xMDPiBjOJc+rcjZHtN5cJJGcvAwOWTjE9u1i28sDFWALTwyROvsuUKuLohrz7VFaJbhiDw==", "dependencies": { "queue-microtask": "^1.1.2", "readable-stream": "^4.0.0" @@ -7475,6 +7530,18 @@ "@rdfjs/types": "*" } }, + "node_modules/rdf-isomorphic": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rdf-isomorphic/-/rdf-isomorphic-1.3.1.tgz", + "integrity": "sha512-6uIhsXTVp2AtO6f41PdnRV5xZsa0zVZQDTBdn0br+DZuFf5M/YD+T6m8hKDUnALI6nFL/IujTMLgEs20MlNidQ==", + "dev": true, + "dependencies": { + "@rdfjs/types": "*", + "hash.js": "^1.1.7", + "rdf-string": "^1.6.0", + "rdf-terms": "^1.7.0" + } + }, "node_modules/rdf-js": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/rdf-js/-/rdf-js-4.0.2.tgz", @@ -7483,6 +7550,27 @@ "@rdfjs/types": "*" } }, + "node_modules/rdf-string": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/rdf-string/-/rdf-string-1.6.3.tgz", + "integrity": "sha512-HIVwQ2gOqf+ObsCLSUAGFZMIl3rh9uGcRf1KbM85UDhKqP+hy6qj7Vz8FKt3GA54RiThqK3mNcr66dm1LP0+6g==", + "dev": true, + "dependencies": { + "@rdfjs/types": "*", + "rdf-data-factory": "^1.1.0" + } + }, + "node_modules/rdf-terms": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/rdf-terms/-/rdf-terms-1.11.0.tgz", + "integrity": "sha512-iKlVgnMopRKl9pHVNrQrax7PtZKRCT/uJIgYqvuw1VVQb88zDvurtDr1xp0rt7N9JtKtFwUXoIQoEsjyRo20qQ==", + "dev": true, + "dependencies": { + "@rdfjs/types": "*", + "rdf-data-factory": "^1.1.0", + "rdf-string": "^1.6.0" + } + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -10459,6 +10547,12 @@ "@babel/types": "^7.3.0" } }, + "@types/content-type": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.5.tgz", + "integrity": "sha512-dgMN+syt1xb7Hk8LU6AODOfPlvz5z1CbXpPuJE5ZrX9STfBOIXF09pEB8N7a97WT9dbngt3ksDCm6GW6yMrxfQ==", + "dev": true + }, "@types/dotenv-flow": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@types/dotenv-flow/-/dotenv-flow-3.2.0.tgz", @@ -10554,6 +10648,16 @@ "@types/lodash": "*" } }, + "@types/n3": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@types/n3/-/n3-1.16.0.tgz", + "integrity": "sha512-g/67NVSihmIoIZT3/J462NhJrmpCw+5WUkkKqpCE9YxNEWzBwKavGPP+RUmG6DIm5GrW4GPunuxLJ0Yn/GgNjQ==", + "dev": true, + "requires": { + "@rdfjs/types": "^1.1.0", + "@types/node": "*" + } + }, "@types/node": { "version": "20.3.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", @@ -11376,8 +11480,7 @@ "content-type": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "convert-source-map": { "version": "2.0.0", @@ -12204,6 +12307,11 @@ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true }, + "event-emitter-promisify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/event-emitter-promisify/-/event-emitter-promisify-1.1.0.tgz", + "integrity": "sha512-uyHG8gjwYGDlKoo0Txtx/u1HI1ubj0FK0rVqI4O0s1EymQm4iAEMbrS5B+XFlSaS8SZ3xzoKX+YHRZk8Nk/bXg==" + }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -12813,6 +12921,16 @@ "has-symbols": "^1.0.2" } }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -13818,6 +13936,18 @@ "readable-stream": "^4.0.0" } }, + "jsonld-streaming-serializer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jsonld-streaming-serializer/-/jsonld-streaming-serializer-2.1.0.tgz", + "integrity": "sha512-COHdLoeMTnrqHMoFhN3PoAwqnrKrpPC7/ACb0WbELYvt+HSOIFN3v4IJP7fOtLNQ4GeaeYkvbeWJ7Jo4EjxMDw==", + "requires": { + "@rdfjs/types": "*", + "@types/readable-stream": "^2.3.13", + "buffer": "^6.0.3", + "jsonld-context-parser": "^2.0.0", + "readable-stream": "^4.0.0" + } + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -13993,6 +14123,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -14027,9 +14163,9 @@ "dev": true }, "n3": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/n3/-/n3-1.16.3.tgz", - "integrity": "sha512-9caLSZuMW1kdlPxEN4ka6E4E8a5QKoZ2emxpW+zHMofI+Bo92nJhN//wNub15S5T9I4c6saEqdGEu+YXJqMZVA==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/n3/-/n3-1.17.0.tgz", + "integrity": "sha512-dYdkyUM4tMWHSEf9xMDPiBjOJc+rcjZHtN5cJJGcvAwOWTjE9u1i28sDFWALTwyROvsuUKuLohrz7VFaJbhiDw==", "requires": { "queue-microtask": "^1.1.2", "readable-stream": "^4.0.0" @@ -14756,6 +14892,18 @@ "@rdfjs/types": "*" } }, + "rdf-isomorphic": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rdf-isomorphic/-/rdf-isomorphic-1.3.1.tgz", + "integrity": "sha512-6uIhsXTVp2AtO6f41PdnRV5xZsa0zVZQDTBdn0br+DZuFf5M/YD+T6m8hKDUnALI6nFL/IujTMLgEs20MlNidQ==", + "dev": true, + "requires": { + "@rdfjs/types": "*", + "hash.js": "^1.1.7", + "rdf-string": "^1.6.0", + "rdf-terms": "^1.7.0" + } + }, "rdf-js": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/rdf-js/-/rdf-js-4.0.2.tgz", @@ -14764,6 +14912,27 @@ "@rdfjs/types": "*" } }, + "rdf-string": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/rdf-string/-/rdf-string-1.6.3.tgz", + "integrity": "sha512-HIVwQ2gOqf+ObsCLSUAGFZMIl3rh9uGcRf1KbM85UDhKqP+hy6qj7Vz8FKt3GA54RiThqK3mNcr66dm1LP0+6g==", + "dev": true, + "requires": { + "@rdfjs/types": "*", + "rdf-data-factory": "^1.1.0" + } + }, + "rdf-terms": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/rdf-terms/-/rdf-terms-1.11.0.tgz", + "integrity": "sha512-iKlVgnMopRKl9pHVNrQrax7PtZKRCT/uJIgYqvuw1VVQb88zDvurtDr1xp0rt7N9JtKtFwUXoIQoEsjyRo20qQ==", + "dev": true, + "requires": { + "@rdfjs/types": "*", + "rdf-data-factory": "^1.1.0", + "rdf-string": "^1.6.0" + } + }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", diff --git a/package.json b/package.json index 0dfcbb31..6498a1cc 100644 --- a/package.json +++ b/package.json @@ -62,8 +62,10 @@ "@rdfjs/dataset": "2.0.1", "@rdfjs/types": "^1.1.0", "@rushstack/eslint-patch": "^1.1.4", + "@types/content-type": "^1.1.5", "@types/dotenv-flow": "^3.1.1", "@types/jest": "^29.2.2", + "@types/n3": "^1.16.0", "@types/node": "^20.1.2", "@types/rdfjs__dataset": "2.0.3", "dotenv-flow": "^3.2.0", @@ -71,6 +73,7 @@ "jest": "^29.3.0", "jest-environment-jsdom": "^29.3.0", "prettier": "2.8.8", + "rdf-isomorphic": "^1.3.1", "rollup": "^3.1.0", "rollup-plugin-typescript2": "^0.35.0", "ts-jest": "^29.0.3", @@ -84,7 +87,11 @@ }, "dependencies": { "@inrupt/solid-client": "^1.25.2", - "@inrupt/universal-fetch": "^1.0.1" + "@inrupt/universal-fetch": "^1.0.1", + "content-type": "^1.0.5", + "event-emitter-promisify": "^1.1.0", + "jsonld-streaming-serializer": "^2.1.0", + "n3": "^1.17.0" }, "publishConfig": { "access": "public" diff --git a/src/common/common.mock.ts b/src/common/common.mock.ts index 4106b65c..97ee5383 100644 --- a/src/common/common.mock.ts +++ b/src/common/common.mock.ts @@ -45,9 +45,16 @@ export type CredentialClaims = VerifiableClaims & { }; export const defaultVerifiableClaims: VerifiableClaims = { - "@context": { ex: "https://example.org/ns/" }, - id: "ex:someCredentialInstance", - type: [...defaultCredentialTypes, "ex:spaceDogCertificate"], + "@context": [ + // { ex: "https://example.org/ns/" }, + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + id: "https://example.org/ns/someCredentialInstance", + type: [ + ...defaultCredentialTypes, + "https://example.org/ns/spaceDogCertificate", + ], proofType: "Ed25519Signature2018", proofCreated: "2021-08-19T16:08:31Z", proofVerificationMethod: @@ -63,16 +70,19 @@ export const defaultCredentialClaims: CredentialClaims = { issuanceDate: "1960-08-19T16:08:31Z", subjectId: "https://some.webid.provider/strelka", subjectClaims: { - "ex:status": "https://example.org/ns/GoodDog", - "ex:passengerOf": "https://example.org/ns/Korabl-Sputnik2", + "https://example.org/ns/status": "https://example.org/ns/GoodDog", + "https://example.org/ns/passengerOf": + "https://example.org/ns/Korabl-Sputnik2", }, }; export const mockPartialCredential = ( - claims?: Partial + claims?: Partial, + id?: string ): Record => { return { - id: claims?.id, + "@context": claims?.["@context"], + id: id ?? claims?.id, type: claims?.type, issuer: claims?.issuer, issuanceDate: claims?.issuanceDate, @@ -90,14 +100,39 @@ export const mockPartialCredential = ( }; }; +export const mockPartialCredential2Proofs = ( + claims?: Partial, + id?: string +): Record => { + return { + ...mockPartialCredential(claims, id), + proof: [ + mockPartialCredential(claims, id).proof, + mockPartialCredential(claims, id).proof, + ], + }; +}; + export const mockCredential = ( claims: CredentialClaims ): VerifiableCredential => { return mockPartialCredential(claims) as VerifiableCredential; }; -export const mockDefaultCredential = (): VerifiableCredential => { - return mockPartialCredential(defaultCredentialClaims) as VerifiableCredential; +export const mockDefaultCredential = (id?: string): VerifiableCredential => { + return mockPartialCredential( + defaultCredentialClaims, + id + ) as VerifiableCredential; +}; + +export const mockDefaultCredential2Proofs = ( + id?: string +): VerifiableCredential => { + return mockPartialCredential2Proofs( + defaultCredentialClaims, + id + ) as VerifiableCredential; }; export const mockPartialPresentation = ( diff --git a/src/common/common.test.ts b/src/common/common.test.ts index d62cc87b..6f0959aa 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -22,10 +22,13 @@ import { jest, describe, it, expect } from "@jest/globals"; import { Response } from "@inrupt/universal-fetch"; import type * as UniversalFetch from "@inrupt/universal-fetch"; +import { isomorphic } from "rdf-isomorphic"; +import { DataFactory, Store } from "n3"; import type { VerifiableCredential } from "./common"; import { concatenateContexts, getVerifiableCredential, + getVerifiableCredentialFromStore, isVerifiableCredential, isVerifiablePresentation, } from "./common"; @@ -36,7 +39,9 @@ import { mockDefaultPresentation, mockPartialPresentation, defaultVerifiableClaims, + mockDefaultCredential2Proofs, } from "./common.mock"; +import { jsonLdStringToStore, jsonLdToStore } from "../parser/jsonld"; jest.mock("@inrupt/universal-fetch", () => { const fetchModule = jest.requireActual( @@ -44,7 +49,9 @@ jest.mock("@inrupt/universal-fetch", () => { ) as typeof UniversalFetch; return { ...fetchModule, - fetch: jest.fn<(typeof UniversalFetch)["fetch"]>(), + fetch: jest.fn<(typeof UniversalFetch)["fetch"]>(() => { + throw new Error("Fetch should not be called"); + }), }; }); @@ -265,7 +272,9 @@ describe("getVerifiableCredential", () => { "@inrupt/universal-fetch" ) as jest.Mocked; mockedFetchModule.fetch.mockResolvedValueOnce( - new Response(JSON.stringify(mockDefaultCredential())) + new Response(JSON.stringify(mockDefaultCredential()), { + headers: new Headers([["content-type", "application/json"]]), + }) ); const redirectUrl = new URL("https://redirect.url"); @@ -286,7 +295,9 @@ describe("getVerifiableCredential", () => { const mockedFetch = jest .fn<(typeof UniversalFetch)["fetch"]>() .mockResolvedValueOnce( - new Response(JSON.stringify(mockDefaultCredential())) + new Response(JSON.stringify(mockDefaultCredential()), { + headers: new Headers([["content-type", "application/json"]]), + }) ); await getVerifiableCredential("https://some.vc", { @@ -335,16 +346,646 @@ describe("getVerifiableCredential", () => { ).rejects.toThrow(/https:\/\/some.vc.*Verifiable Credential/); }); - it("returns the fetched VC and the redirect URL", async () => { + it("throws if the dereferenced data has an unsupported content type", async () => { const mockedFetch = jest .fn<(typeof UniversalFetch)["fetch"]>() .mockResolvedValueOnce( new Response(JSON.stringify(mockDefaultCredential())) ); + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow(/unsupported Content-Type/); + }); + + it("throws if the dereferenced data is empty", async () => { + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify({}), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + /Expected exactly one Verifiable Credential.* received: 0/ + ); + }); + + it("throws if the vc is a blank node", async () => { + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response( + JSON.stringify({ + "@type": "https://www.w3.org/2018/credentials#VerifiableCredential", + }), + { + headers: new Headers([["content-type", "application/json"]]), + } + ) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + "Expected the Verifiable Credential in [https://some.vc] to be a Named Node, received: BlankNode" + ); + }); + + it("throws if the vc has a type that is a literal", async () => { + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response( + JSON.stringify({ + "@context": "https://www.w3.org/2018/credentials/v1", + "@id": "http://example.org/my/vc", + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": [ + { + "@id": + "https://www.w3.org/2018/credentials#VerifiableCredential", + }, + "str", + ], + }), + { + headers: new Headers([["content-type", "application/json"]]), + } + ) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + "Expected all VC types to be Named Nodes but received [str] of termType [Literal]" + ); + }); + + it("throws if the dereferenced data has 2 vcs", async () => { + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response( + JSON.stringify([ + mockDefaultCredential(), + mockDefaultCredential("http://example.org/mockVC2"), + ]), + { + headers: new Headers([["content-type", "application/json"]]), + } + ) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + /Expected exactly one Verifiable Credential.* received: 2/ + ); + }); + + it("throws if the dereferenced data has 2 proofs", async () => { + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mockDefaultCredential2Proofs()), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + /Expected exactly one \[https:\/\/w3id.org\/security#proof\].* received: 2/ + ); + }); + + it("throws if the date field is not a valid xsd:dateTime", async () => { + const mocked = mockDefaultCredential(); + mocked.issuanceDate = "http://example.org/not/a/date"; + + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mocked), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + /Invalid dateTime in VC \[http:\/\/example.org\/not\/a\/date\]/ + ); + }); + + it("throws if the date field is a string", async () => { + const mocked = mockDefaultCredential(); + delete (mocked as any).issuanceDate; + mocked["https://www.w3.org/2018/credentials#issuanceDate"] = + "http://example.org/not/a/date"; + + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mocked), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + /Expected issuanceDate to have dataType \[http:\/\/www.w3.org\/2001\/XMLSchema#dateTime\], received: \[http:\/\/www.w3.org\/2001\/XMLSchema#string\]/ + ); + }); + + it("throws if the date field is an IRI", async () => { + const mocked = mockDefaultCredential(); + delete (mocked as any).issuanceDate; + mocked["https://www.w3.org/2018/credentials#issuanceDate"] = { + "@id": "http://example.org/not/a/date", + }; + + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mocked), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + /Expected issuanceDate to be a Literal, received: NamedNode/ + ); + }); + + it("throws if the issuer is a string", async () => { + const mocked = mockDefaultCredential(); + (mocked as any).issuer = { "@value": "my string" }; + + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mocked), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + "Expected property [https://www.w3.org/2018/credentials#issuer] of the Verifiable Credential [https://example.org/ns/someCredentialInstance] to be a NamedNode, received: Literal" + ); + }); + + it("should error when there is a graph in the credential subject", async () => { + const mocked = mockDefaultCredential(); + mocked.credentialSubject = { + ...mocked.credentialSubject, + "https://example.org/ns/passengerOf": [ + { "@id": "http://example.org/v1" }, + { "@id": "http://example.org/v2" }, + { + "https://example.org/ns/predicate": "str", + }, + ], + }; + + const store = await jsonLdToStore(mocked); + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicate"), + DataFactory.defaultGraph() as any + ) + ); + + await expect( + getVerifiableCredentialFromStore(store, "https://some.vc") + ).rejects.toThrow("Unexpected term type: DefaultGraph"); + }); + + it("should error when there is a non-NamedNode predicate in the credential subject", async () => { + const mocked = mockDefaultCredential(); + mocked.credentialSubject = { + ...mocked.credentialSubject, + "https://example.org/ns/passengerOf": [ + { "@id": "http://example.org/v1" }, + { "@id": "http://example.org/v2" }, + { + "https://example.org/ns/predicate": "str", + }, + ], + }; + + const store = await jsonLdToStore(mocked); + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.literal("https://example.org/predicate") as any, + DataFactory.namedNode("https://example.org/ns/object") + ) + ); + + await expect( + getVerifiableCredentialFromStore(store, "https://some.vc") + ).rejects.toThrow("Predicate must be a namedNode"); + }); + + it("should handle credential subjects with multiple objects", async () => { + const mocked = mockDefaultCredential(); + mocked.credentialSubject = { + ...mocked.credentialSubject, + "https://example.org/ns/passengerOf": [ + { "@id": "http://example.org/v1" }, + { "@id": "http://example.org/v2" }, + ], + "https://example.org/my/predicate/i": { + "https://example.org/my/predicate": "object", + }, + }; + + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mocked), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + const vc = await getVerifiableCredential("https://some.vc", { fetch: mockedFetch, }); - expect(vc).toStrictEqual(mockDefaultCredential()); + + expect(vc).toMatchObject({ + ...mocked, + credentialSubject: { + ...mocked.credentialSubject, + // All objects are fully expanded to use @value + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + // This is how blank nodes are represented + "https://example.org/my/predicate/i": { + "https://example.org/my/predicate": { + "@value": "object", + }, + }, + }, + type: [ + // Unknown types like http://example.org/spaceDog are excluded + "VerifiableCredential", + ], + }); + }); + + it("should error if more than 2 subjects in proof graph", async () => { + const store = new Store([ + DataFactory.quad( + DataFactory.namedNode("http://example.org/vc"), + DataFactory.namedNode("https://w3id.org/security#proof"), + DataFactory.namedNode("http://example.org/proofGraph") + ), + DataFactory.quad( + DataFactory.namedNode("http://example.org/s"), + DataFactory.namedNode("http://example.org/p"), + DataFactory.namedNode("http://example.org/o"), + DataFactory.namedNode("http://example.org/proofGraph") + ), + DataFactory.quad( + DataFactory.namedNode("http://example.org/s2"), + DataFactory.namedNode("http://example.org/p2"), + DataFactory.namedNode("http://example.org/o2"), + DataFactory.namedNode("http://example.org/proofGraph") + ), + DataFactory.quad( + DataFactory.namedNode("http://example.org/vc"), + DataFactory.namedNode( + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" + ), + DataFactory.namedNode( + "https://www.w3.org/2018/credentials#VerifiableCredential" + ) + ), + ]); + + await expect( + getVerifiableCredentialFromStore(store, "http://example.org/vc") + ).rejects.toThrow( + "Expected exactly one proof to live in the proofs graph, received 2" + ); + }); + + it("should error if proof graph made about different subject", async () => { + const store = new Store([ + DataFactory.quad( + DataFactory.namedNode("http://example.org/vc2"), + DataFactory.namedNode("https://w3id.org/security#proof"), + DataFactory.namedNode("http://example.org/proofGraph") + ), + DataFactory.quad( + DataFactory.namedNode("http://example.org/s"), + DataFactory.namedNode("http://example.org/p"), + DataFactory.namedNode("http://example.org/o"), + DataFactory.namedNode("http://example.org/proofGraph") + ), + DataFactory.quad( + DataFactory.namedNode("http://example.org/s2"), + DataFactory.namedNode("http://example.org/p2"), + DataFactory.namedNode("http://example.org/o2"), + DataFactory.namedNode("http://example.org/proofGraph") + ), + DataFactory.quad( + DataFactory.namedNode("http://example.org/vc"), + DataFactory.namedNode( + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" + ), + DataFactory.namedNode( + "https://www.w3.org/2018/credentials#VerifiableCredential" + ) + ), + ]); + + await expect( + getVerifiableCredentialFromStore(store, "http://example.org/vc") + ).rejects.toThrow( + "Expected exactly one [https://w3id.org/security#proof] for the Verifiable Credential http://example.org/vc, received: 0" + ); + }); + + // TODO: String predicates for VC + + it("throws if there are 2 proof values", async () => { + const mocked = mockDefaultCredential(); + (mocked.proof as any).proofValue = [mocked.proof.proofValue, "abc"]; + + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mocked), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + await expect( + getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }) + ).rejects.toThrow( + /Expected exactly one \[https:\/\/w3id.org\/security#proofValue\] for the Verifiable Credential https:\/\/example.org\/ns\/someCredentialInstance, received: 2/ + ); + }); + + it("returns the fetched VC and the redirect URL", async () => { + const mockedFetch = jest + .fn<(typeof UniversalFetch)["fetch"]>() + .mockResolvedValueOnce( + new Response(JSON.stringify(mockDefaultCredential()), { + headers: new Headers([["content-type", "application/json"]]), + }) + ); + + const vc = await getVerifiableCredential("https://some.vc", { + fetch: mockedFetch, + }); + + const res = await jsonLdStringToStore( + JSON.stringify(mockDefaultCredential()) + ); + expect(vc).toMatchObject( + Object.assign(mockDefaultCredential(), { + size: 13, + // We always re-frame w.r.t to this context + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + // The credentials subject is re-framed to make the fact that the + // objects are literals explicit + credentialSubject: { + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + id: "https://some.webid.provider/strelka", + }, + // Any types outside of those in our VC and Inrupt context are removed + type: ["VerifiableCredential"], + }) + ); + + const meaninglessQuad = DataFactory.quad( + DataFactory.namedNode("http://example.org/a"), + DataFactory.namedNode("http://example.org/b"), + DataFactory.namedNode("http://example.org/c") + ); + + const issuerQuad = DataFactory.quad( + DataFactory.namedNode("https://example.org/ns/someCredentialInstance"), + DataFactory.namedNode("https://www.w3.org/2018/credentials#issuer"), + DataFactory.namedNode("https://some.vc.issuer/in-ussr") + ); + + expect(isomorphic([...vc], [...res])).toBe(true); + expect(isomorphic([...vc.match()], [...res])).toBe(true); + expect(() => vc.add(meaninglessQuad)).toThrow("Cannot mutate this dataset"); + expect(() => vc.delete(meaninglessQuad)).toThrow( + "Cannot mutate this dataset" + ); + expect(vc.has(meaninglessQuad)).toBe(false); + expect(vc.has(issuerQuad)).toBe(true); + expect(vc.size).toBe(13); + expect( + vc.match( + DataFactory.namedNode("https://example.org/ns/someCredentialInstance") + ).size + ).toBe(6); + }); + + it("should handle non standard proof type", async () => { + const store = await jsonLdToStore(mockDefaultCredential()); + + for (const quad of store.match( + null, + DataFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), + DataFactory.namedNode("https://w3id.org/security#Ed25519Signature2018") + )) { + store.delete(quad); + store.add( + DataFactory.quad( + quad.subject, + quad.predicate, + DataFactory.namedNode("https://w3id.org/security#notARealSignature"), + quad.graph + ) + ); + } + + expect( + await getVerifiableCredentialFromStore(store, "https://some.vc") + ).toMatchObject( + Object.assign(mockDefaultCredential(), { + size: 13, + // We always re-frame w.r.t to this context + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + // The credentials subject is re-framed to make the fact that the + // objects are literals explicit + credentialSubject: { + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + id: "https://some.webid.provider/strelka", + }, + // Any types outside of those in our VC and Inrupt context are removed + type: ["VerifiableCredential"], + proof: { + ...mockDefaultCredential().proof, + // Proof purpose has full URI as compacting this relies on the + // context of the "type" + proofPurpose: "https://w3id.org/security#assertionMethod", + type: "https://w3id.org/security#notARealSignature", + }, + }) + ); + }); + + it("should handle multiple known types", async () => { + const store = await jsonLdToStore(mockDefaultCredential()); + + for (const quad of store.match( + null, + DataFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), + DataFactory.namedNode( + "https://www.w3.org/2018/credentials#VerifiableCredential" + ) + )) { + store.add( + DataFactory.quad( + quad.subject, + quad.predicate, + DataFactory.namedNode( + "https://www.w3.org/2018/credentials#VerifiablePresentation" + ), + quad.graph + ) + ); + } + + expect( + await getVerifiableCredentialFromStore(store, "https://some.vc") + ).toMatchObject( + Object.assign(mockDefaultCredential(), { + size: 14, + // We always re-frame w.r.t to this context + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + // The credentials subject is re-framed to make the fact that the + // objects are literals explicit + credentialSubject: { + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + id: "https://some.webid.provider/strelka", + }, + // Any types outside of those in our VC and Inrupt context are removed + type: ["VerifiableCredential", "VerifiablePresentation"], + }) + ); + }); + + it("should handle credential subject with a blank node", async () => { + const store = await jsonLdToStore(mockDefaultCredential()); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicate"), + DataFactory.blankNode("b2") + ) + ); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicate"), + DataFactory.namedNode("https://example.org/object") + ) + ); + + store.add( + DataFactory.quad( + DataFactory.blankNode("b2"), + DataFactory.namedNode("https://example.org/predicate"), + DataFactory.blankNode("b2") + ) + ); + + expect( + await getVerifiableCredentialFromStore(store, "https://some.vc") + ).toMatchObject( + Object.assign(mockDefaultCredential(), { + size: 15, + // We always re-frame w.r.t to this context + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + // The credentials subject is re-framed to make the fact that the + // objects are literals explicit + credentialSubject: { + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + id: "https://some.webid.provider/strelka", + // TODO: Work out why the blank node is not expanded + "https://example.org/predicate": { + "@id": "https://example.org/object" + }, + }, + // Any types outside of those in our VC and Inrupt context are removed + type: ["VerifiableCredential"], + }) + ); }); }); diff --git a/src/common/common.ts b/src/common/common.ts index a050da44..05927dc9 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -31,6 +31,13 @@ import { getJsonLdParser, } from "@inrupt/solid-client"; import { fetch as uniFetch } from "@inrupt/universal-fetch"; +import { Util } from "jsonld-streaming-serializer"; +import type { DatasetCore } from "@rdfjs/types"; +import type { Store, Term } from "n3"; +import { DataFactory as DF } from "n3"; +import parse from "content-type"; +import VcContext from "../parser/contexts/vc"; +import { getVcContext, jsonLdResponseToStore } from "../parser/jsonld"; export type Iri = string; /** @@ -410,29 +417,347 @@ export async function getVerifiableCredential( options?: Partial<{ fetch: typeof fetch; }> -): Promise { +): Promise { const authFetch = options?.fetch ?? uniFetch; - return authFetch(vcUrl as string) - .then(async (response) => { - if (!response.ok) { - throw new Error( - `Fetching the Verifiable Credential [${vcUrl}] failed: ${response.status} ${response.statusText}` - ); - } - try { - return normalizeVc(await response.json()); - } catch (e) { - throw new Error( - `Parsing the Verifiable Credential [${vcUrl}] as JSON failed: ${e}` - ); + const response = await authFetch(vcUrl); + return getVerifiableCredentialFromResponse(response, vcUrl, options); +} + +/** + * @param response Takes a response from a VC service and checks that it has the correct status and content type + * @param vcUrl The URL of the VC + * @returns The input response + */ +function validateVcResponse( + response: globalThis.Response, + vcUrl: string +): globalThis.Response { + if (!response.ok) { + throw new Error( + `Fetching the Verifiable Credential [${vcUrl}] failed: ${response.status} ${response.statusText}` + ); + } + + const contentType = response.headers.get("Content-Type"); + + // Ignoring since the test suite always adds a content type + /* istanbul ignore if */ + if (!contentType) { + throw new Error( + `Fetching the Verifiable Credential [${vcUrl}] failed: Response does not have a Content-Type header; expected application/ld+json` + ); + } + + const parsedContentType = parse.parse(contentType); + const [mediaType, subtypesString] = parsedContentType.type.split("/"); + const subtypes = subtypesString.split("+"); + + if ( + mediaType !== "application" || + // TODO: See if the response is expected to include the ld + // || !subtypes.includes('ld') + !subtypes.includes("json") + ) { + throw new Error( + `Fetching the Verifiable Credential [${vcUrl}] failed: Response has an unsupported Content-Type [${contentType}]; expected application/ld+json` + ); + } + + return response; +} + +async function responseToVcStore( + response: globalThis.Response, + vcUrl: UrlString, + options?: Partial<{ + fetch: typeof fetch; + }> +): Promise { + try { + return await jsonLdResponseToStore(validateVcResponse(response, vcUrl), { + fetch: options?.fetch, + baseIRI: vcUrl, + }); + } catch (e) { + throw new Error( + `Parsing the Verifiable Credential [${vcUrl}] as JSON-LD failed: ${e}` + ); + } +} + +const VC = "https://www.w3.org/2018/credentials#"; +const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; +const XSD = "http://www.w3.org/2001/XMLSchema#"; +const SEC = "https://w3id.org/security#"; +const CRED = "https://www.w3.org/2018/credentials#"; + +/** + * Dereference a VC URL, and verify that the resulting content is valid. + * + * @param vcUrl The URL of the VC. + * @param options Options to customize the function behavior. + * - options.fetch: Specify a WHATWG-compatible authenticated fetch. + * @returns The dereferenced VC if valid. Throws otherwise. + * @since 0.4.0 + */ +export async function getVerifiableCredentialFromResponse( + response: Response, + vcUrl: UrlString, + options?: Partial<{ + fetch: typeof fetch; + }> +): Promise { + const vcStore = await responseToVcStore(response, vcUrl, options); + return getVerifiableCredentialFromStore(vcStore, vcUrl); +} + +export async function getVerifiableCredentialFromStore( + vcStore: Store, + vcUrl: UrlString +): Promise { + const context = await getVcContext(); + + const vcs = vcStore.getSubjects( + `${RDF}type`, + `${VC}VerifiableCredential`, + DF.defaultGraph() + ); + if (vcs.length !== 1) { + throw new Error( + `Expected exactly one Verifiable Credential in [${vcUrl}], received: ${vcs.length}` + ); + } + + const [vc] = vcs; + if (vc.termType !== "NamedNode") { + throw new Error( + `Expected the Verifiable Credential in [${vcUrl}] to be a Named Node, received: ${vc.termType}` + ); + } + + const type: string[] = []; + for (const t of vcStore.getObjects(vc, `${RDF}type`, DF.defaultGraph())) { + if (t.termType !== "NamedNode") { + throw new Error( + `Expected all VC types to be Named Nodes but received [${t.value}] of termType [${t.termType}]` + ); + } + + const compact = context.compactIri(t.value, true); + + if (/^[a-z]+$/i.test(compact)) type.push(compact); + } + + function getSingleObject( + fullProperty: string, + subject?: Term, + graph: Term = DF.defaultGraph() + ): Term { + const objects = vcStore.getObjects(subject ?? vc, fullProperty, graph); + + if (objects.length !== 1) { + throw new Error( + `Expected exactly one [${fullProperty}] for the Verifiable Credential ${vc.value}, received: ${objects.length}` + ); + } + + return objects[0]; + } + + function getSingleObjectOfTermType( + fullProperty: string, + subject?: Term, + graph?: Term, + termType = "NamedNode", + customContext = context + ) { + const object = getSingleObject(fullProperty, subject, graph); + + if (object.termType !== termType) { + throw new Error( + `Expected property [${fullProperty}] of the Verifiable Credential [${vc.value}] to be a ${termType}, received: ${object.termType}` + ); + } + + // TODO: Make sure that Literals with URIs are correclty handled here + return object.termType === "NamedNode" + ? customContext.compactIri(object.value, true) + : object.value; + } + + function getSingleDateTime( + fullProperty: string, + subject?: Term, + graph?: Term + ) { + const object = getSingleObject(fullProperty, subject, graph); + + if (object.termType !== "Literal") { + throw new Error( + `Expected issuanceDate to be a Literal, received: ${object.termType}` + ); + } + if (!object.datatype.equals(DF.namedNode(`${XSD}dateTime`))) { + throw new Error( + `Expected issuanceDate to have dataType [${XSD}dateTime], received: [${object.datatype.value}]` + ); + } + + if (Number.isNaN(Date.parse(object.value))) { + throw new Error(`Invalid dateTime in VC [${object.value}]`); + } + + return object.value; + } + + // The proof lives within a named graph + const proofGraph = getSingleObject(`${SEC}proof`); + const proofs = vcStore.getSubjects(null, null, proofGraph); + + if (proofs.length !== 1) { + throw new Error( + `Expected exactly one proof to live in the proofs graph, received ${proofs.length}` + ); + } + + const [proof] = proofs; + const proofType = getSingleObjectOfTermType(`${RDF}type`, proof, proofGraph); + + const proposedContext = (VcContext["@context"] as any)[proofType]?.[ + "@context" + ]; + + let proofContext = context; + let proofPurposeContext = context; + + if (typeof proposedContext === "object") { + proofContext = proofPurposeContext = await getVcContext(proposedContext); + if (typeof proposedContext.proofPurpose?.["@context"] === "object") { + proofPurposeContext = await getVcContext( + proposedContext, + proposedContext.proofPurpose["@context"] + ); + } + } + + function getProperties(subject: Term, writtenTerms: string[] = []) { + const object: Record = {}; + + for (const predicate of vcStore.getPredicates( + subject, + null, + DF.defaultGraph() + )) { + if (predicate.termType !== "NamedNode") { + throw new Error("Predicate must be a namedNode"); } - }) - .then((vc) => { - if (!isVerifiableCredential(vc)) { - throw new Error( - `The value received from [${vcUrl}] is not a Verifiable Credential` + + const compact = context.compactIri(predicate.value, true); + const objects: any[] = vcStore + .getObjects(subject, predicate, DF.defaultGraph()) + .map((obj) => writeObject(obj, writtenTerms)) + .filter( + (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1 ); + + if (objects.length === 1) { + [object[compact]] = objects; + } else if (objects.length > 1) { + object[compact] = objects; } - return vc; - }); + } + + return object; + } + + function writeObject(object: Term, writtenTerms: string[]) { + switch (object.termType) { + case "BlankNode": + return writtenTerms.includes(object.value) + ? {} + : getProperties(object, [...writtenTerms, object.value]); + case "NamedNode": + // TODO: See if we actually want to do compacting here + // given how ConsentStatusExplicitlyGiven as the full + // URI in e2e tests, and this may make it look like a + // literal + // return context.compactIri(object.value, true); + case "Literal": + return Util.termToValue(object, context); + default: + throw new Error(`Unexpected term type: ${object.termType}`); + } + } + + const credentialSubject = getSingleObjectOfTermType( + `${CRED}credentialSubject` + ); + return { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + id: vc.value, + // It is possible to have multiple claims in a credential subject + // we do not support this + // https://www.w3.org/TR/vc-data-model/#example-specifying-multiple-subjects-in-a-verifiable-credential + credentialSubject: { + ...getProperties(DF.namedNode(credentialSubject)), + id: credentialSubject, + }, + issuer: getSingleObjectOfTermType(`${CRED}issuer`), + issuanceDate: getSingleDateTime(`${CRED}issuanceDate`), + type, + proof: { + created: getSingleDateTime( + "http://purl.org/dc/terms/created", + proof, + proofGraph + ), + proofPurpose: getSingleObjectOfTermType( + `${SEC}proofPurpose`, + proof, + proofGraph, + "NamedNode", + proofPurposeContext + ), + type: proofType, + verificationMethod: getSingleObjectOfTermType( + `${SEC}verificationMethod`, + proof, + proofGraph, + "NamedNode", + proofContext + ), + proofValue: getSingleObjectOfTermType( + `${SEC}proofValue`, + proof, + proofGraph, + "Literal" + ), + }, + + // Make this a DatasetCore without polluting the object with + // all of the properties present in the N3.Store + [Symbol.iterator]() { + return vcStore[Symbol.iterator](); + }, + has(quad) { + return vcStore.has(quad); + }, + match(subject, predicate, object, graph) { + // We need to cast to DatasetCore because the N3.Store + // type uses an internal type for Term rather than the @rdfjs/types Term + return (vcStore as DatasetCore).match(subject, predicate, object, graph); + }, + add() { + throw new Error("Cannot mutate this dataset"); + }, + delete() { + throw new Error("Cannot mutate this dataset"); + }, + get size() { + return vcStore.size; + }, + }; } diff --git a/src/parser/contexts/index.ts b/src/parser/contexts/index.ts new file mode 100644 index 00000000..5703114f --- /dev/null +++ b/src/parser/contexts/index.ts @@ -0,0 +1,27 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// +import VC from "./vc"; +import Inrupt from "./inrupt"; + +export default { + "https://www.w3.org/2018/credentials/v1": VC, + "https://schema.inrupt.com/credentials/v1.jsonld": Inrupt, +} as const; diff --git a/src/parser/contexts/inrupt.ts b/src/parser/contexts/inrupt.ts new file mode 100644 index 00000000..51e2841f --- /dev/null +++ b/src/parser/contexts/inrupt.ts @@ -0,0 +1,149 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// + +/** + * The custom Inrupt context for verifiable credentials + * @see https://schema.inrupt.com/credentials/v1.jsonld + */ +export default { + "@context": { + "@version": 1.1, + "@protected": true, + ldp: "http://www.w3.org/ns/ldp#", + acl: "http://www.w3.org/ns/auth/acl#", + gc: "https://w3id.org/GConsent#", + vc: "http://www.w3.org/ns/solid/vc#", + xsd: "http://www.w3.org/2001/XMLSchema#", + issuerService: { + "@id": "vc:issuerService", + "@type": "@id", + }, + statusService: { + "@id": "vc:statusService", + "@type": "@id", + }, + verifierService: { + "@id": "vc:verifierService", + "@type": "@id", + }, + derivationService: { + "@id": "vc:derivationService", + "@type": "@id", + }, + proofService: { + "@id": "vc:proofService", + "@type": "@id", + }, + availabilityService: { + "@id": "vc:availabilityService", + "@type": "@id", + }, + submissionService: { + "@id": "vc:submissionService", + "@type": "@id", + }, + supportedSignatureTypes: { + "@id": "vc:supportedSignatureTypes", + "@type": "@id", + }, + include: { + "@id": "vc:include", + "@type": "@id", + }, + SolidAccessGrant: "vc:SolidAccessGrant", + SolidAccessRequest: "vc:SolidAccessRequest", + ExpiredVerifiableCredential: "vc:ExpiredVerifiableCredential", + inbox: { + "@id": "ldp:inbox", + "@type": "@id", + }, + Read: "acl:Read", + Write: "acl:Write", + Append: "acl:Append", + mode: { + "@id": "acl:mode", + "@type": "@vocab", + }, + Consent: "gc:Consent", + ConsentStatusExpired: "gc:ConsentStatusExpired", + ConsentStatusExplicitlyGiven: "gc:ConsentStatusExplicitlyGiven", + ConsentStatusGivenByDelegation: "gc:ConsentStatusGivenByDelegation", + ConsentStatusImplicitlyGiven: "gc:ConsentStatusImplicitlyGiven", + ConsentStatusInvalidated: "gc:ConsentStatusInvalidated", + ConsentStatusNotGiven: "gc:ConsentStatusNotGiven", + ConsentStatusRefused: "gc:ConsentStatusRefused", + ConsentStatusRequested: "gc:ConsentStatusRequested", + ConsentStatusUnknown: "gc:ConsentStatusUnknown", + ConsentStatusWithdrawn: "gc:ConsentStatusWithdrawn", + forPersonalData: { + "@id": "gc:forPersonalData", + "@type": "@id", + }, + forProcessing: { + "@id": "gc:forProcessing", + "@type": "@id", + }, + forPurpose: { + "@id": "gc:forPurpose", + "@type": "@id", + }, + hasConsent: { + "@id": "gc:hasConsent", + "@type": "@id", + }, + hasContext: { + "@id": "gc:hasContext", + "@type": "@id", + }, + hasStatus: { + "@id": "gc:hasStatus", + "@type": "@vocab", + }, + inMedium: { + "@id": "gc:inMedium", + "@type": "@id", + }, + isConsentForDataSubject: { + "@id": "gc:isConsentForDataSubject", + "@type": "@id", + }, + isProvidedTo: { + "@id": "gc:isProvidedTo", + "@type": "@id", + }, + isProvidedToPerson: { + "@id": "gc:isProvidedToPerson", + "@type": "@id", + }, + isProvidedToController: { + "@id": "gc:isProvidedToController", + "@type": "@id", + }, + providedConsent: { + "@id": "gc:providedConsent", + "@type": "@id", + }, + inherit: { + "@id": "urn:uuid:71ab2f68-a68b-4452-b968-dd23e0570227", + "@type": "xsd:boolean", + }, + }, +} as const; diff --git a/src/parser/contexts/vc.ts b/src/parser/contexts/vc.ts new file mode 100644 index 00000000..36f6b852 --- /dev/null +++ b/src/parser/contexts/vc.ts @@ -0,0 +1,275 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// + +/** + * The Verifiable Credentials context. + * @see https://www.w3.org/2018/credentials/v1 + */ +export default { + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + VerifiableCredential: { + "@id": "https://www.w3.org/2018/credentials#VerifiableCredential", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + cred: "https://www.w3.org/2018/credentials#", + sec: "https://w3id.org/security#", + xsd: "http://www.w3.org/2001/XMLSchema#", + credentialSchema: { + "@id": "cred:credentialSchema", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + cred: "https://www.w3.org/2018/credentials#", + JsonSchemaValidator2018: "cred:JsonSchemaValidator2018", + }, + }, + credentialStatus: { "@id": "cred:credentialStatus", "@type": "@id" }, + credentialSubject: { "@id": "cred:credentialSubject", "@type": "@id" }, + evidence: { "@id": "cred:evidence", "@type": "@id" }, + expirationDate: { + "@id": "cred:expirationDate", + "@type": "xsd:dateTime", + }, + holder: { "@id": "cred:holder", "@type": "@id" }, + issued: { "@id": "cred:issued", "@type": "xsd:dateTime" }, + issuer: { "@id": "cred:issuer", "@type": "@id" }, + issuanceDate: { "@id": "cred:issuanceDate", "@type": "xsd:dateTime" }, + proof: { "@id": "sec:proof", "@type": "@id", "@container": "@graph" }, + refreshService: { + "@id": "cred:refreshService", + "@type": "@id", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + cred: "https://www.w3.org/2018/credentials#", + ManualRefreshService2018: "cred:ManualRefreshService2018", + }, + }, + termsOfUse: { "@id": "cred:termsOfUse", "@type": "@id" }, + validFrom: { "@id": "cred:validFrom", "@type": "xsd:dateTime" }, + validUntil: { "@id": "cred:validUntil", "@type": "xsd:dateTime" }, + }, + }, + VerifiablePresentation: { + "@id": "https://www.w3.org/2018/credentials#VerifiablePresentation", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + cred: "https://www.w3.org/2018/credentials#", + sec: "https://w3id.org/security#", + holder: { "@id": "cred:holder", "@type": "@id" }, + proof: { "@id": "sec:proof", "@type": "@id", "@container": "@graph" }, + verifiableCredential: { + "@id": "cred:verifiableCredential", + "@type": "@id", + "@container": "@graph", + }, + }, + }, + EcdsaSecp256k1Signature2019: { + "@id": "https://w3id.org/security#EcdsaSecp256k1Signature2019", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + sec: "https://w3id.org/security#", + xsd: "http://www.w3.org/2001/XMLSchema#", + challenge: "sec:challenge", + created: { + "@id": "http://purl.org/dc/terms/created", + "@type": "xsd:dateTime", + }, + domain: "sec:domain", + expires: { "@id": "sec:expiration", "@type": "xsd:dateTime" }, + jws: "sec:jws", + nonce: "sec:nonce", + proofPurpose: { + "@id": "sec:proofPurpose", + "@type": "@vocab", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + sec: "https://w3id.org/security#", + assertionMethod: { + "@id": "sec:assertionMethod", + "@type": "@id", + "@container": "@set", + }, + authentication: { + "@id": "sec:authenticationMethod", + "@type": "@id", + "@container": "@set", + }, + }, + }, + proofValue: "sec:proofValue", + verificationMethod: { "@id": "sec:verificationMethod", "@type": "@id" }, + }, + }, + EcdsaSecp256r1Signature2019: { + "@id": "https://w3id.org/security#EcdsaSecp256r1Signature2019", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + sec: "https://w3id.org/security#", + xsd: "http://www.w3.org/2001/XMLSchema#", + challenge: "sec:challenge", + created: { + "@id": "http://purl.org/dc/terms/created", + "@type": "xsd:dateTime", + }, + domain: "sec:domain", + expires: { "@id": "sec:expiration", "@type": "xsd:dateTime" }, + jws: "sec:jws", + nonce: "sec:nonce", + proofPurpose: { + "@id": "sec:proofPurpose", + "@type": "@vocab", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + sec: "https://w3id.org/security#", + assertionMethod: { + "@id": "sec:assertionMethod", + "@type": "@id", + "@container": "@set", + }, + authentication: { + "@id": "sec:authenticationMethod", + "@type": "@id", + "@container": "@set", + }, + }, + }, + proofValue: "sec:proofValue", + verificationMethod: { "@id": "sec:verificationMethod", "@type": "@id" }, + }, + }, + Ed25519Signature2018: { + "@id": "https://w3id.org/security#Ed25519Signature2018", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + sec: "https://w3id.org/security#", + xsd: "http://www.w3.org/2001/XMLSchema#", + challenge: "sec:challenge", + created: { + "@id": "http://purl.org/dc/terms/created", + "@type": "xsd:dateTime", + }, + domain: "sec:domain", + expires: { "@id": "sec:expiration", "@type": "xsd:dateTime" }, + jws: "sec:jws", + nonce: "sec:nonce", + proofPurpose: { + "@id": "sec:proofPurpose", + "@type": "@vocab", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + sec: "https://w3id.org/security#", + assertionMethod: { + "@id": "sec:assertionMethod", + "@type": "@id", + "@container": "@set", + }, + authentication: { + "@id": "sec:authenticationMethod", + "@type": "@id", + "@container": "@set", + }, + }, + }, + proofValue: "sec:proofValue", + verificationMethod: { "@id": "sec:verificationMethod", "@type": "@id" }, + }, + }, + RsaSignature2018: { + "@id": "https://w3id.org/security#RsaSignature2018", + "@context": { + "@version": 1.1, + "@protected": true, + challenge: "sec:challenge", + created: { + "@id": "http://purl.org/dc/terms/created", + "@type": "xsd:dateTime", + }, + domain: "sec:domain", + expires: { "@id": "sec:expiration", "@type": "xsd:dateTime" }, + jws: "sec:jws", + nonce: "sec:nonce", + proofPurpose: { + "@id": "sec:proofPurpose", + "@type": "@vocab", + "@context": { + "@version": 1.1, + "@protected": true, + id: "@id", + type: "@type", + sec: "https://w3id.org/security#", + assertionMethod: { + "@id": "sec:assertionMethod", + "@type": "@id", + "@container": "@set", + }, + authentication: { + "@id": "sec:authenticationMethod", + "@type": "@id", + "@container": "@set", + }, + }, + }, + proofValue: "sec:proofValue", + verificationMethod: { "@id": "sec:verificationMethod", "@type": "@id" }, + }, + }, + proof: { + "@id": "https://w3id.org/security#proof", + "@type": "@id", + "@container": "@graph", + }, + }, +} as const; diff --git a/src/parser/jsonld.test.ts b/src/parser/jsonld.test.ts new file mode 100644 index 00000000..86e3c137 --- /dev/null +++ b/src/parser/jsonld.test.ts @@ -0,0 +1,187 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// + +import { jest, it, describe, expect, beforeAll } from "@jest/globals"; +import { Response } from "@inrupt/universal-fetch"; +import type * as UniversalFetch from "@inrupt/universal-fetch"; +import { DataFactory as DF } from "n3"; +import { isomorphic } from "rdf-isomorphic"; +import type { JsonLdContextNormalized } from "jsonld-context-parser"; +import { jsonLdResponseToStore, jsonLdToStore, getVcContext } from "./jsonld"; + +const fetcher: (typeof UniversalFetch)["fetch"] = async (url) => { + if (url !== "https://example.com/myContext") { + throw new Error("Unexpected URL"); + } + + return new Response( + JSON.stringify({ + "@context": { + Person: "http://xmlns.com/foaf/0.1/Person", + xsd: "http://www.w3.org/2001/XMLSchema#", + name: "http://xmlns.com/foaf/0.1/name", + nickname: "http://xmlns.com/foaf/0.1/nick", + affiliation: "http://schema.org/affiliation", + }, + }), + { + headers: new Headers([["content-type", "application/ld+json"]]), + } + ); +}; + +jest.mock("@inrupt/universal-fetch", () => { + const fetchModule = jest.requireActual( + "@inrupt/universal-fetch" + ) as typeof UniversalFetch; + return { + ...fetchModule, + fetch: jest.fn<(typeof UniversalFetch)["fetch"]>(), + }; +}); + +const data = { + "@context": "https://www.w3.org/2018/credentials/v1", + id: "https://some.example#credential", + type: ["VerifiableCredential"], + issuer: "https://some.example", +}; + +const dataExampleContext = { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://example.com/myContext", + ], + id: "https://some.example#credential", + name: "Inrupt", +}; + +const dataWithPrefix = { + "@context": [ + { ex: "https://some.example#" }, + "https://www.w3.org/2018/credentials/v1", + ], + id: "ex:credential", + type: ["VerifiableCredential"], + issuer: "https://some.example", +}; + +const result = [ + DF.quad( + DF.namedNode("https://some.example#credential"), + DF.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), + DF.namedNode("https://www.w3.org/2018/credentials#VerifiableCredential") + ), + DF.quad( + DF.namedNode("https://some.example#credential"), + DF.namedNode("https://www.w3.org/2018/credentials#issuer"), + DF.namedNode("https://some.example") + ), +]; + +describe("jsonLdResponseToStore", () => { + it("converting fetch response to a store", async () => { + const response = new Response(JSON.stringify(data)); + expect( + isomorphic([...(await jsonLdResponseToStore(response))], result) + ).toBe(true); + }); + + // This is currently broken - see https://github.com/rubensworks/jsonld-streaming-parser.js/issues/112 + it.skip("converting fetch response with custom prefix definition to a store", async () => { + const response = new Response(JSON.stringify(dataWithPrefix)); + const quads = [...(await jsonLdResponseToStore(response))]; + expect(isomorphic(quads, result)).toBe(true); + }); + + it("rejects on empty fetch response", async () => { + await expect(jsonLdResponseToStore(new Response())).rejects.toThrow( + "Empty response body. Expected JSON-LD." + ); + }); + + it("rejects on invalid JSON-LD", async () => { + await expect(jsonLdResponseToStore(new Response("{"))).rejects.toThrow( + "Error parsing JSON-LD: [Error: Unclosed document]." + ); + }); + + it("converting fetch response with custom context to a store", async () => { + const response = new Response(JSON.stringify(dataExampleContext)); + expect( + isomorphic( + [...(await jsonLdResponseToStore(response, { fetch: fetcher }))], + [ + DF.quad( + DF.namedNode("https://some.example#credential"), + DF.namedNode("http://xmlns.com/foaf/0.1/name"), + DF.literal("Inrupt") + ), + ] + ) + ).toBe(true); + }); +}); + +describe("jsonLdToStore", () => { + it("converting valid POJO to store", async () => { + expect(isomorphic([...(await jsonLdToStore(data))], result)).toBe(true); + }); +}); + +describe("getVcContext", () => { + let context: JsonLdContextNormalized; + + beforeAll(async () => { + context = await getVcContext(); + }); + + it("should be able to compact and expand IRIs from the VC context", () => { + expect( + context.compactIri( + "https://www.w3.org/2018/credentials#VerifiableCredential", + true + ) + ).toBe("VerifiableCredential"); + expect(context.expandTerm("VerifiableCredential", true)).toBe( + "https://www.w3.org/2018/credentials#VerifiableCredential" + ); + }); + + it("should be able to compact and expand IRIs from the Inrupt context", () => { + expect(context.compactIri("https://w3id.org/GConsent#Consent", true)).toBe( + "Consent" + ); + expect(context.expandTerm("Consent", true)).toBe( + "https://w3id.org/GConsent#Consent" + ); + }); + + it("should not compact and expand IRIs not in the VC or Inrupt context", () => { + expect( + context.compactIri( + "https://example.org/credentials#VerifiableCredential", + true + ) + ).toBe("https://example.org/credentials#VerifiableCredential"); + expect(context.expandTerm("VC", true)).toBe("VC"); + }); +}); diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts new file mode 100644 index 00000000..cca136be --- /dev/null +++ b/src/parser/jsonld.ts @@ -0,0 +1,146 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// + +/* eslint-disable max-classes-per-file */ +import defaultFetch from "@inrupt/universal-fetch"; +import { promisifyEventEmitter } from "event-emitter-promisify"; +import type { + IJsonLdContext, + JsonLdContextNormalized, +} from "jsonld-context-parser"; +import { ContextParser, FetchDocumentLoader } from "jsonld-context-parser"; +import { JsonLdParser } from "jsonld-streaming-parser"; +import { Store } from "n3"; +import CONTEXTS from "./contexts"; +import type { JsonLd } from "../common/common"; + +/** + * Creates a context for use with the VC library + */ +// FIXME: See if our access grants specific context should be passed +// through as a parameter instead +export function getVcContext( + ...contexts: IJsonLdContext[] +): Promise { + const myParser = new ContextParser({ + documentLoader: new CachedFetchDocumentLoader(), + }); + return myParser.parse([...Object.values(CONTEXTS), ...contexts]); +} + +/** + * A JSON-LD document loader with the standard context for VCs pre-loaded + */ +class CachedFetchDocumentLoader extends FetchDocumentLoader { + public async load(url: string): Promise { + if (Object.keys(CONTEXTS).includes(url)) { + return CONTEXTS[url as keyof typeof CONTEXTS]; + } + // FIXME: See if we want to error on other contexts + return super.load(url); + } +} + +interface Options { + fetch?: typeof globalThis.fetch; + baseIRI?: string; +} + +/** + * Our internal JsonLd Parser with a cached VC context + */ +export class IJsonLdParser extends JsonLdParser { + constructor(options?: Options) { + super({ + documentLoader: new CachedFetchDocumentLoader( + options?.fetch ?? defaultFetch + ), + baseIRI: options?.baseIRI, + }); + } +} + +/** + * Gets an N3 store from a JSON-LD string + * @param response A JSON-LD string + * @param options An optional fetch function for dereferencing remote contexts + * @returns A store containing the Quads in the JSON-LD response + */ +export async function jsonLdStringToStore(data: string, options?: Options) { + try { + const parser = new IJsonLdParser(options); + const store = new Store(); + const storePromise = promisifyEventEmitter(store.import(parser), store); + parser.write(data); + parser.end(); + return await storePromise; + } catch (e) { + throw new Error(`Error parsing JSON-LD: [${e}].`); + } +} + +/** + * Gets an N3 store from a JSON-LD response to a fetch request + * @param response A JSON-LD response + * @param options An optional fetch function for dereferencing remote contexts + * @returns A store containing the Quads in the JSON-LD response + */ +export async function jsonLdResponseToStore( + response: globalThis.Response, + options?: Options +): Promise { + if (response.body === null) + throw new Error("Empty response body. Expected JSON-LD."); + + return jsonLdStringToStore(await response.text(), options); + + // FIXME: Use this logic once node 16 is deprecated + // This won't work with node-fetch (and hence versions of Node lower than 16.8) because + // node-fetch does not have #getReader implemented. + // You will likely encounter the following error when trying to implement it this way and testing it in Jest: + // TypeError: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. + // Received an instance of Uint8Array. + // I believe this error is caused by the `fetch` and `TextEncoder` polyfills in our environment + // causing multiple versions of the Buffer or Uint8Array classes existing and hence `instanceof` + // checks not behaving as intended. + + // const reader = response.body.getReader(); + // const parser = new IJsonLdParser({ fetch: options?.fetch, baseIRI: response.url }); + // const store = new Store(); + // const result = promisifyEventEmitter(store.import(parser), store); + // let value = await reader.read(); + // while (!value.done) { + // parser.write(value.value); + // value = await reader.read(); + // } + // parser.end(); + // return result; +} + +/** + * Gets an N3 store from a JSON-LD as an Object + * @param response JSON-LD as an Object + * @param options An optional fetch function for dereferencing remote contexts + * @returns A store containing the Quads in the JSON-LD response + */ +export function jsonLdToStore(data: JsonLd, options?: Options) { + return jsonLdStringToStore(JSON.stringify(data), options); +} From 519ed716f0317d59fe4a8ab2a9d9418c5ac2319d Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Thu, 13 Jul 2023 14:51:21 +1000 Subject: [PATCH 02/35] chore: get full test coverage --- src/common/common.test.ts | 60 ++++++++++++++++++++- src/common/common.ts | 107 +++++++++++++++++++++----------------- src/parser/jsonld.ts | 26 ++++----- 3 files changed, 129 insertions(+), 64 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 6f0959aa..b0522c9b 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -19,6 +19,7 @@ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +/* eslint-disable @typescript-eslint/no-explicit-any */ import { jest, describe, it, expect } from "@jest/globals"; import { Response } from "@inrupt/universal-fetch"; import type * as UniversalFetch from "@inrupt/universal-fetch"; @@ -882,6 +883,61 @@ describe("getVerifiableCredential", () => { ); }); + it("should apply the correct context for a given proof", async () => { + const store = await jsonLdToStore(mockDefaultCredential()); + + for (const quad of store.match( + null, + DataFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), + DataFactory.namedNode("https://w3id.org/security#Ed25519Signature2018") + )) { + store.removeQuad(quad); + store.add( + DataFactory.quad( + quad.subject, + quad.predicate, + DataFactory.namedNode( + "https://www.w3.org/2018/credentials#VerifiableCredential" + ), + quad.graph + ) + ); + } + + expect( + await getVerifiableCredentialFromStore(store, "https://some.vc") + ).toMatchObject( + Object.assign(mockDefaultCredential(), { + size: 13, + // We always re-frame w.r.t to this context + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + // The credentials subject is re-framed to make the fact that the + // objects are literals explicit + credentialSubject: { + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + id: "https://some.webid.provider/strelka", + }, + // Any types outside of those in our VC and Inrupt context are removed + type: ["VerifiableCredential"], + proof: { + ...mockDefaultCredential().proof, + // Proof purpose has a prefix because assertionMethod is not + // defined as a term in the VerifiableCredential subContext + proofPurpose: "sec:assertionMethod", + type: "VerifiableCredential", + }, + }) + ); + }); + it("should handle multiple known types", async () => { const store = await jsonLdToStore(mockDefaultCredential()); @@ -962,7 +1018,7 @@ describe("getVerifiableCredential", () => { await getVerifiableCredentialFromStore(store, "https://some.vc") ).toMatchObject( Object.assign(mockDefaultCredential(), { - size: 15, + size: 16, // We always re-frame w.r.t to this context "@context": [ "https://www.w3.org/2018/credentials/v1", @@ -980,7 +1036,7 @@ describe("getVerifiableCredential", () => { id: "https://some.webid.provider/strelka", // TODO: Work out why the blank node is not expanded "https://example.org/predicate": { - "@id": "https://example.org/object" + "@id": "https://example.org/object", }, }, // Any types outside of those in our VC and Inrupt context are removed diff --git a/src/common/common.ts b/src/common/common.ts index 05927dc9..1608ba50 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -403,26 +403,6 @@ export async function getVerifiableCredentialApiConfiguration( }; } -/** - * Dereference a VC URL, and verify that the resulting content is valid. - * - * @param vcUrl The URL of the VC. - * @param options Options to customize the function behavior. - * - options.fetch: Specify a WHATWG-compatible authenticated fetch. - * @returns The dereferenced VC if valid. Throws otherwise. - * @since 0.4.0 - */ -export async function getVerifiableCredential( - vcUrl: UrlString, - options?: Partial<{ - fetch: typeof fetch; - }> -): Promise { - const authFetch = options?.fetch ?? uniFetch; - const response = await authFetch(vcUrl); - return getVerifiableCredentialFromResponse(response, vcUrl, options); -} - /** * @param response Takes a response from a VC service and checks that it has the correct status and content type * @param vcUrl The URL of the VC @@ -492,25 +472,8 @@ const SEC = "https://w3id.org/security#"; const CRED = "https://www.w3.org/2018/credentials#"; /** - * Dereference a VC URL, and verify that the resulting content is valid. - * - * @param vcUrl The URL of the VC. - * @param options Options to customize the function behavior. - * - options.fetch: Specify a WHATWG-compatible authenticated fetch. - * @returns The dereferenced VC if valid. Throws otherwise. - * @since 0.4.0 + * @hidden */ -export async function getVerifiableCredentialFromResponse( - response: Response, - vcUrl: UrlString, - options?: Partial<{ - fetch: typeof fetch; - }> -): Promise { - const vcStore = await responseToVcStore(response, vcUrl, options); - return getVerifiableCredentialFromStore(vcStore, vcUrl); -} - export async function getVerifiableCredentialFromStore( vcStore: Store, vcUrl: UrlString @@ -623,20 +586,28 @@ export async function getVerifiableCredentialFromStore( const [proof] = proofs; const proofType = getSingleObjectOfTermType(`${RDF}type`, proof, proofGraph); - const proposedContext = (VcContext["@context"] as any)[proofType]?.[ - "@context" - ]; + const proposedContextTemp = + VcContext["@context"][proofType as keyof (typeof VcContext)["@context"]]; + const proposedContext = + typeof proposedContextTemp === "object" && + "@context" in proposedContextTemp && + proposedContextTemp["@context"]; let proofContext = context; let proofPurposeContext = context; if (typeof proposedContext === "object") { - proofContext = proofPurposeContext = await getVcContext(proposedContext); - if (typeof proposedContext.proofPurpose?.["@context"] === "object") { + proofContext = await getVcContext(proposedContext); + if ( + "proofPurpose" in proposedContext && + typeof proposedContext.proofPurpose["@context"] === "object" + ) { proofPurposeContext = await getVcContext( proposedContext, proposedContext.proofPurpose["@context"] ); + } else { + proofPurposeContext = proofContext; } } @@ -653,8 +624,10 @@ export async function getVerifiableCredentialFromStore( } const compact = context.compactIri(predicate.value, true); - const objects: any[] = vcStore + const objects = vcStore .getObjects(subject, predicate, DF.defaultGraph()) + // writeObject and getProperties depend on each other circularly + // eslint-disable-next-line @typescript-eslint/no-use-before-define .map((obj) => writeObject(obj, writtenTerms)) .filter( (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1 @@ -676,12 +649,8 @@ export async function getVerifiableCredentialFromStore( return writtenTerms.includes(object.value) ? {} : getProperties(object, [...writtenTerms, object.value]); + // eslint-disable-next-line no-fallthrough case "NamedNode": - // TODO: See if we actually want to do compacting here - // given how ConsentStatusExplicitlyGiven as the full - // URI in e2e tests, and this may make it look like a - // literal - // return context.compactIri(object.value, true); case "Literal": return Util.termToValue(object, context); default: @@ -761,3 +730,43 @@ export async function getVerifiableCredentialFromStore( }, }; } + +/** + * Dereference a VC URL, and verify that the resulting content is valid. + * + * @param vcUrl The URL of the VC. + * @param options Options to customize the function behavior. + * - options.fetch: Specify a WHATWG-compatible authenticated fetch. + * @returns The dereferenced VC if valid. Throws otherwise. + * @since 0.4.0 + */ +export async function getVerifiableCredentialFromResponse( + response: Response, + vcUrl: UrlString, + options?: Partial<{ + fetch: typeof fetch; + }> +): Promise { + const vcStore = await responseToVcStore(response, vcUrl, options); + return getVerifiableCredentialFromStore(vcStore, vcUrl); +} + +/** + * Dereference a VC URL, and verify that the resulting content is valid. + * + * @param vcUrl The URL of the VC. + * @param options Options to customize the function behavior. + * - options.fetch: Specify a WHATWG-compatible authenticated fetch. + * @returns The dereferenced VC if valid. Throws otherwise. + * @since 0.4.0 + */ +export async function getVerifiableCredential( + vcUrl: UrlString, + options?: Partial<{ + fetch: typeof fetch; + }> +): Promise { + const authFetch = options?.fetch ?? uniFetch; + const response = await authFetch(vcUrl); + return getVerifiableCredentialFromResponse(response, vcUrl, options); +} diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index cca136be..e8430312 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -32,6 +32,19 @@ import { Store } from "n3"; import CONTEXTS from "./contexts"; import type { JsonLd } from "../common/common"; +/** + * A JSON-LD document loader with the standard context for VCs pre-loaded + */ +class CachedFetchDocumentLoader extends FetchDocumentLoader { + public async load(url: string): Promise { + if (Object.keys(CONTEXTS).includes(url)) { + return CONTEXTS[url as keyof typeof CONTEXTS]; + } + // FIXME: See if we want to error on other contexts + return super.load(url); + } +} + /** * Creates a context for use with the VC library */ @@ -46,19 +59,6 @@ export function getVcContext( return myParser.parse([...Object.values(CONTEXTS), ...contexts]); } -/** - * A JSON-LD document loader with the standard context for VCs pre-loaded - */ -class CachedFetchDocumentLoader extends FetchDocumentLoader { - public async load(url: string): Promise { - if (Object.keys(CONTEXTS).includes(url)) { - return CONTEXTS[url as keyof typeof CONTEXTS]; - } - // FIXME: See if we want to error on other contexts - return super.load(url); - } -} - interface Options { fetch?: typeof globalThis.fetch; baseIRI?: string; From 0bca5fd1b9a2915afbb170cac7a15be203d48d8f Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:34:19 +1000 Subject: [PATCH 03/35] fix: improve blank node handling --- src/common/common.test.ts | 132 +++++++++++++++++++++++++++++++++++++- src/common/common.ts | 11 +++- 2 files changed, 138 insertions(+), 5 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index b0522c9b..1eeb2144 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -739,8 +739,6 @@ describe("getVerifiableCredential", () => { ); }); - // TODO: String predicates for VC - it("throws if there are 2 proof values", async () => { const mocked = mockDefaultCredential(); (mocked.proof as any).proofValue = [mocked.proof.proofValue, "abc"]; @@ -990,10 +988,60 @@ describe("getVerifiableCredential", () => { it("should handle credential subject with a blank node", async () => { const store = await jsonLdToStore(mockDefaultCredential()); + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicateBnode"), + DataFactory.blankNode("b2") + ) + ); + store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicate"), + DataFactory.namedNode("https://example.org/object") + ) + ); + + expect( + await getVerifiableCredentialFromStore(store, "https://some.vc") + ).toMatchObject( + Object.assign(mockDefaultCredential(), { + size: 15, + // We always re-frame w.r.t to this context + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + // The credentials subject is re-framed to make the fact that the + // objects are literals explicit + credentialSubject: { + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + id: "https://some.webid.provider/strelka", + "https://example.org/predicate": { + "@id": "https://example.org/object", + }, + "https://example.org/predicateBnode": {}, + }, + // Any types outside of those in our VC and Inrupt context are removed + type: ["VerifiableCredential"], + }) + ); + }); + + it("should handle credential subject with a self-referential blank node", async () => { + const store = await jsonLdToStore(mockDefaultCredential()); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicateBnode"), DataFactory.blankNode("b2") ) ); @@ -1034,10 +1082,88 @@ describe("getVerifiableCredential", () => { "@value": "https://example.org/ns/GoodDog", }, id: "https://some.webid.provider/strelka", - // TODO: Work out why the blank node is not expanded "https://example.org/predicate": { "@id": "https://example.org/object", }, + "https://example.org/predicateBnode": { + "@id": "_:b1", + "https://example.org/predicate": { + "@id": "_:b1", + }, + }, + }, + // Any types outside of those in our VC and Inrupt context are removed + type: ["VerifiableCredential"], + }) + ); + }); + + it("should handle credential subject with a self-referential blank node and stand-alone blank node", async () => { + const store = await jsonLdToStore(mockDefaultCredential()); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicateBnode"), + DataFactory.blankNode("b2") + ) + ); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicateBnode"), + DataFactory.blankNode("b3") + ) + ); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicate"), + DataFactory.namedNode("https://example.org/object") + ) + ); + + store.add( + DataFactory.quad( + DataFactory.blankNode("b2"), + DataFactory.namedNode("https://example.org/predicate"), + DataFactory.blankNode("b2") + ) + ); + + expect( + await getVerifiableCredentialFromStore(store, "https://some.vc") + ).toMatchObject( + Object.assign(mockDefaultCredential(), { + size: 17, + // We always re-frame w.r.t to this context + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schema.inrupt.com/credentials/v1.jsonld", + ], + // The credentials subject is re-framed to make the fact that the + // objects are literals explicit + credentialSubject: { + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + id: "https://some.webid.provider/strelka", + "https://example.org/predicate": { + "@id": "https://example.org/object", + }, + "https://example.org/predicateBnode": [{ + "@id": "_:b1", + "https://example.org/predicate": { + "@id": "_:b1", + }, + },{ + "@id": "_:b2" + }], }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], diff --git a/src/common/common.ts b/src/common/common.ts index 1608ba50..9e12139d 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -643,12 +643,19 @@ export async function getVerifiableCredentialFromStore( return object; } + let i = 0; + const data: Record = {}; + function writeObject(object: Term, writtenTerms: string[]) { switch (object.termType) { - case "BlankNode": - return writtenTerms.includes(object.value) + case "BlankNode": { + const obj = writtenTerms.includes(object.value) ? {} : getProperties(object, [...writtenTerms, object.value]); + + obj["@id"] = `_:b${(data[object.value] ??= (i += 1))}`; + return obj; + } // eslint-disable-next-line no-fallthrough case "NamedNode": case "Literal": From cc7e9586b1dbd7ec834f8b6516d56a2675844cef Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:39:12 +1000 Subject: [PATCH 04/35] chore: run lint:fix --- src/common/common.test.ts | 15 +++++++++------ src/common/common.ts | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 1eeb2144..0d9e13a7 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -1156,14 +1156,17 @@ describe("getVerifiableCredential", () => { "https://example.org/predicate": { "@id": "https://example.org/object", }, - "https://example.org/predicateBnode": [{ - "@id": "_:b1", - "https://example.org/predicate": { + "https://example.org/predicateBnode": [ + { "@id": "_:b1", + "https://example.org/predicate": { + "@id": "_:b1", + }, + }, + { + "@id": "_:b2", }, - },{ - "@id": "_:b2" - }], + ], }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], diff --git a/src/common/common.ts b/src/common/common.ts index 9e12139d..4b57b18b 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -653,7 +653,8 @@ export async function getVerifiableCredentialFromStore( ? {} : getProperties(object, [...writtenTerms, object.value]); - obj["@id"] = `_:b${(data[object.value] ??= (i += 1))}`; + // eslint-disable-next-line no-multi-assign + obj["@id"] = `_:b${(data[object.value] ??= i += 1)}`; return obj; } // eslint-disable-next-line no-fallthrough From 2fe1dcc6cb1f716475bbae8d99530fd6d559a0b1 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:34:29 +1000 Subject: [PATCH 05/35] chore: remove global linting exception --- src/common/common.test.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 0d9e13a7..3e16de23 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -18,13 +18,11 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // - -/* eslint-disable @typescript-eslint/no-explicit-any */ import { jest, describe, it, expect } from "@jest/globals"; import { Response } from "@inrupt/universal-fetch"; import type * as UniversalFetch from "@inrupt/universal-fetch"; import { isomorphic } from "rdf-isomorphic"; -import { DataFactory, Store } from "n3"; +import { DataFactory, Quad_Object, Quad_Predicate, Quad_Subject, Store } from "n3"; import type { VerifiableCredential } from "./common"; import { concatenateContexts, @@ -498,7 +496,9 @@ describe("getVerifiableCredential", () => { it("throws if the date field is a string", async () => { const mocked = mockDefaultCredential(); - delete (mocked as any).issuanceDate; + // issuanceDate is required on the VC type + // @ts-expect-error + delete mocked.issuanceDate; mocked["https://www.w3.org/2018/credentials#issuanceDate"] = "http://example.org/not/a/date"; @@ -521,7 +521,9 @@ describe("getVerifiableCredential", () => { it("throws if the date field is an IRI", async () => { const mocked = mockDefaultCredential(); - delete (mocked as any).issuanceDate; + // issuanceDate is required on the VC type + // @ts-expect-error + delete mocked.issuanceDate; mocked["https://www.w3.org/2018/credentials#issuanceDate"] = { "@id": "http://example.org/not/a/date", }; @@ -545,7 +547,9 @@ describe("getVerifiableCredential", () => { it("throws if the issuer is a string", async () => { const mocked = mockDefaultCredential(); - (mocked as any).issuer = { "@value": "my string" }; + // issuer is of type string on the VC type + // @ts-expect-error + mocked.issuer = { "@value": "my string" }; const mockedFetch = jest .fn<(typeof UniversalFetch)["fetch"]>() @@ -582,7 +586,7 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicate"), - DataFactory.defaultGraph() as any + DataFactory.defaultGraph() as unknown as Quad_Object ) ); @@ -608,7 +612,7 @@ describe("getVerifiableCredential", () => { store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), - DataFactory.literal("https://example.org/predicate") as any, + DataFactory.literal("https://example.org/predicate") as unknown as Quad_Predicate, DataFactory.namedNode("https://example.org/ns/object") ) ); @@ -741,7 +745,9 @@ describe("getVerifiableCredential", () => { it("throws if there are 2 proof values", async () => { const mocked = mockDefaultCredential(); - (mocked.proof as any).proofValue = [mocked.proof.proofValue, "abc"]; + // Proof value is a string not string[] in VC type + // @ts-expect-error + mocked.proof.proofValue = [mocked.proof.proofValue, "abc"]; const mockedFetch = jest .fn<(typeof UniversalFetch)["fetch"]>() From cdddf9778ad50544bd221fdf0c70b3429ae20a7b Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:38:04 +1000 Subject: [PATCH 06/35] chore: fix lint errors --- src/common/common.test.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 3e16de23..e411611c 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -22,7 +22,7 @@ import { jest, describe, it, expect } from "@jest/globals"; import { Response } from "@inrupt/universal-fetch"; import type * as UniversalFetch from "@inrupt/universal-fetch"; import { isomorphic } from "rdf-isomorphic"; -import { DataFactory, Quad_Object, Quad_Predicate, Quad_Subject, Store } from "n3"; +import { DataFactory, Store } from "n3"; import type { VerifiableCredential } from "./common"; import { concatenateContexts, @@ -496,8 +496,7 @@ describe("getVerifiableCredential", () => { it("throws if the date field is a string", async () => { const mocked = mockDefaultCredential(); - // issuanceDate is required on the VC type - // @ts-expect-error + // @ts-expect-error issuanceDate is required on the VC type delete mocked.issuanceDate; mocked["https://www.w3.org/2018/credentials#issuanceDate"] = "http://example.org/not/a/date"; @@ -521,8 +520,7 @@ describe("getVerifiableCredential", () => { it("throws if the date field is an IRI", async () => { const mocked = mockDefaultCredential(); - // issuanceDate is required on the VC type - // @ts-expect-error + // @ts-expect-error issuanceDate is required on the VC type delete mocked.issuanceDate; mocked["https://www.w3.org/2018/credentials#issuanceDate"] = { "@id": "http://example.org/not/a/date", @@ -547,8 +545,7 @@ describe("getVerifiableCredential", () => { it("throws if the issuer is a string", async () => { const mocked = mockDefaultCredential(); - // issuer is of type string on the VC type - // @ts-expect-error + // @ts-expect-error issuer is of type string on the VC type mocked.issuer = { "@value": "my string" }; const mockedFetch = jest @@ -586,7 +583,8 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicate"), - DataFactory.defaultGraph() as unknown as Quad_Object + // @ts-expect-error DefaultGraph is not allowed as an object + DataFactory.defaultGraph() ) ); @@ -612,7 +610,8 @@ describe("getVerifiableCredential", () => { store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), - DataFactory.literal("https://example.org/predicate") as unknown as Quad_Predicate, + // @ts-expect-error Literal is not allowed as a subject + DataFactory.literal("https://example.org/predicate"), DataFactory.namedNode("https://example.org/ns/object") ) ); @@ -745,8 +744,7 @@ describe("getVerifiableCredential", () => { it("throws if there are 2 proof values", async () => { const mocked = mockDefaultCredential(); - // Proof value is a string not string[] in VC type - // @ts-expect-error + // @ts-expect-error proofValue is a string not string[] in VC type mocked.proof.proofValue = [mocked.proof.proofValue, "abc"]; const mockedFetch = jest From e3b350752db50d23dd72e1b17048a29acacc483b Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:50:41 +1000 Subject: [PATCH 07/35] chore: rename parse to contentTypeParse --- src/common/common.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 4b57b18b..2756b4a9 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -35,7 +35,7 @@ import { Util } from "jsonld-streaming-serializer"; import type { DatasetCore } from "@rdfjs/types"; import type { Store, Term } from "n3"; import { DataFactory as DF } from "n3"; -import parse from "content-type"; +import contentTypeParser from "content-type"; import VcContext from "../parser/contexts/vc"; import { getVcContext, jsonLdResponseToStore } from "../parser/jsonld"; @@ -428,7 +428,7 @@ function validateVcResponse( ); } - const parsedContentType = parse.parse(contentType); + const parsedContentType = contentTypeParser.parse(contentType); const [mediaType, subtypesString] = parsedContentType.type.split("/"); const subtypes = subtypesString.split("+"); From b7478e10e04762f37c442089f09f6a8081acc800 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:54:30 +1000 Subject: [PATCH 08/35] chore: globalThis.Response -> Respnse --- src/common/common.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 2756b4a9..8403d6d0 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -409,9 +409,9 @@ export async function getVerifiableCredentialApiConfiguration( * @returns The input response */ function validateVcResponse( - response: globalThis.Response, + response: Response, vcUrl: string -): globalThis.Response { +): Response { if (!response.ok) { throw new Error( `Fetching the Verifiable Credential [${vcUrl}] failed: ${response.status} ${response.statusText}` @@ -447,7 +447,7 @@ function validateVcResponse( } async function responseToVcStore( - response: globalThis.Response, + response: Response, vcUrl: UrlString, options?: Partial<{ fetch: typeof fetch; From f79793a7c2d93bda9e710f9bd0978c10ec65486d Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:54:55 +1000 Subject: [PATCH 09/35] chore: run lint:fix --- src/common/common.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 8403d6d0..54006cc6 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -408,10 +408,7 @@ export async function getVerifiableCredentialApiConfiguration( * @param vcUrl The URL of the VC * @returns The input response */ -function validateVcResponse( - response: Response, - vcUrl: string -): Response { +function validateVcResponse(response: Response, vcUrl: string): Response { if (!response.ok) { throw new Error( `Fetching the Verifiable Credential [${vcUrl}] failed: ${response.status} ${response.statusText}` From d1021b51a78d08eace9cd301de0693f3a53711b4 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:00:28 +1000 Subject: [PATCH 10/35] globalThis.Response -> Response in jsonld.ts --- src/parser/jsonld.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index e8430312..57e625c6 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -104,7 +104,7 @@ export async function jsonLdStringToStore(data: string, options?: Options) { * @returns A store containing the Quads in the JSON-LD response */ export async function jsonLdResponseToStore( - response: globalThis.Response, + response: Response, options?: Options ): Promise { if (response.body === null) From 8f7a525814b2a4b91759fbc75b2c3d23b0295c5a Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:11:58 +1000 Subject: [PATCH 11/35] chore: use constants for IRIs rather than string templates --- src/common/common.ts | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 54006cc6..88277c62 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -467,6 +467,13 @@ const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; const XSD = "http://www.w3.org/2001/XMLSchema#"; const SEC = "https://w3id.org/security#"; const CRED = "https://www.w3.org/2018/credentials#"; +const RDF_TYPE = `${RDF}type`; +const VERIFIABLE_CREDENTIAL = `${VC}VerifiableCredential`; +const DATE_TIME = `${XSD}dateTime`; +const CREDENTIAL_SUBJECT = `${CRED}credentialSubject`; +const ISSUER = `${CRED}issuer`; +const ISSUANCE_DATE = `${CRED}issuanceDate`; +const PROOF = `${SEC}proof`; /** * @hidden @@ -478,8 +485,8 @@ export async function getVerifiableCredentialFromStore( const context = await getVcContext(); const vcs = vcStore.getSubjects( - `${RDF}type`, - `${VC}VerifiableCredential`, + RDF_TYPE, + VERIFIABLE_CREDENTIAL, DF.defaultGraph() ); if (vcs.length !== 1) { @@ -496,7 +503,7 @@ export async function getVerifiableCredentialFromStore( } const type: string[] = []; - for (const t of vcStore.getObjects(vc, `${RDF}type`, DF.defaultGraph())) { + for (const t of vcStore.getObjects(vc, RDF_TYPE, DF.defaultGraph())) { if (t.termType !== "NamedNode") { throw new Error( `Expected all VC types to be Named Nodes but received [${t.value}] of termType [${t.termType}]` @@ -557,9 +564,9 @@ export async function getVerifiableCredentialFromStore( `Expected issuanceDate to be a Literal, received: ${object.termType}` ); } - if (!object.datatype.equals(DF.namedNode(`${XSD}dateTime`))) { + if (!object.datatype.equals(DF.namedNode(DATE_TIME))) { throw new Error( - `Expected issuanceDate to have dataType [${XSD}dateTime], received: [${object.datatype.value}]` + `Expected issuanceDate to have dataType [${DATE_TIME}], received: [${object.datatype.value}]` ); } @@ -571,7 +578,7 @@ export async function getVerifiableCredentialFromStore( } // The proof lives within a named graph - const proofGraph = getSingleObject(`${SEC}proof`); + const proofGraph = getSingleObject(PROOF); const proofs = vcStore.getSubjects(null, null, proofGraph); if (proofs.length !== 1) { @@ -581,7 +588,7 @@ export async function getVerifiableCredentialFromStore( } const [proof] = proofs; - const proofType = getSingleObjectOfTermType(`${RDF}type`, proof, proofGraph); + const proofType = getSingleObjectOfTermType(RDF_TYPE, proof, proofGraph); const proposedContextTemp = VcContext["@context"][proofType as keyof (typeof VcContext)["@context"]]; @@ -663,9 +670,7 @@ export async function getVerifiableCredentialFromStore( } } - const credentialSubject = getSingleObjectOfTermType( - `${CRED}credentialSubject` - ); + const credentialSubjectTerm = getSingleObjectOfTermType(CREDENTIAL_SUBJECT); return { "@context": [ "https://www.w3.org/2018/credentials/v1", @@ -676,11 +681,11 @@ export async function getVerifiableCredentialFromStore( // we do not support this // https://www.w3.org/TR/vc-data-model/#example-specifying-multiple-subjects-in-a-verifiable-credential credentialSubject: { - ...getProperties(DF.namedNode(credentialSubject)), - id: credentialSubject, + ...getProperties(DF.namedNode(credentialSubjectTerm)), + id: credentialSubjectTerm, }, - issuer: getSingleObjectOfTermType(`${CRED}issuer`), - issuanceDate: getSingleDateTime(`${CRED}issuanceDate`), + issuer: getSingleObjectOfTermType(ISSUER), + issuanceDate: getSingleDateTime(ISSUANCE_DATE), type, proof: { created: getSingleDateTime( From c3f44f1e9a0468d1320570075310cbdec49e2346 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:13:38 +1000 Subject: [PATCH 12/35] chore: rename IJsonLdParser -> CachedJsonLdParser --- src/parser/jsonld.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index 57e625c6..c9744563 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -67,7 +67,7 @@ interface Options { /** * Our internal JsonLd Parser with a cached VC context */ -export class IJsonLdParser extends JsonLdParser { +export class CachedJsonLdParser extends JsonLdParser { constructor(options?: Options) { super({ documentLoader: new CachedFetchDocumentLoader( @@ -86,7 +86,7 @@ export class IJsonLdParser extends JsonLdParser { */ export async function jsonLdStringToStore(data: string, options?: Options) { try { - const parser = new IJsonLdParser(options); + const parser = new CachedJsonLdParser(options); const store = new Store(); const storePromise = promisifyEventEmitter(store.import(parser), store); parser.write(data); From 162545c0c27e7b600cfbfea7a94e7351b79e3021 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:44:47 +1000 Subject: [PATCH 13/35] chore: run lint:fix --- src/common/common.ts | 22 ++++++++++------------ src/parser/contexts/index.ts | 5 ++++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 88277c62..3532b09d 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -37,6 +37,7 @@ import type { Store, Term } from "n3"; import { DataFactory as DF } from "n3"; import contentTypeParser from "content-type"; import VcContext from "../parser/contexts/vc"; +import { context } from "../parser/contexts"; import { getVcContext, jsonLdResponseToStore } from "../parser/jsonld"; export type Iri = string; @@ -246,7 +247,7 @@ export function concatenateContexts(...contexts: unknown[]): unknown { contexts.forEach((additionalContext) => { // Case when the context is an array of IRIs and/or inline contexts if (Array.isArray(additionalContext)) { - additionalContext.forEach((context) => result.add(context)); + additionalContext.forEach((contextEntry) => result.add(contextEntry)); } else if (additionalContext !== null && additionalContext !== undefined) { // Case when the context is a single remote URI or a single inline context result.add(additionalContext); @@ -482,7 +483,7 @@ export async function getVerifiableCredentialFromStore( vcStore: Store, vcUrl: UrlString ): Promise { - const context = await getVcContext(); + const vcContext = await getVcContext(); const vcs = vcStore.getSubjects( RDF_TYPE, @@ -510,7 +511,7 @@ export async function getVerifiableCredentialFromStore( ); } - const compact = context.compactIri(t.value, true); + const compact = vcContext.compactIri(t.value, true); if (/^[a-z]+$/i.test(compact)) type.push(compact); } @@ -536,7 +537,7 @@ export async function getVerifiableCredentialFromStore( subject?: Term, graph?: Term, termType = "NamedNode", - customContext = context + customContext = vcContext ) { const object = getSingleObject(fullProperty, subject, graph); @@ -597,8 +598,8 @@ export async function getVerifiableCredentialFromStore( "@context" in proposedContextTemp && proposedContextTemp["@context"]; - let proofContext = context; - let proofPurposeContext = context; + let proofContext = vcContext; + let proofPurposeContext = vcContext; if (typeof proposedContext === "object") { proofContext = await getVcContext(proposedContext); @@ -627,7 +628,7 @@ export async function getVerifiableCredentialFromStore( throw new Error("Predicate must be a namedNode"); } - const compact = context.compactIri(predicate.value, true); + const compact = vcContext.compactIri(predicate.value, true); const objects = vcStore .getObjects(subject, predicate, DF.defaultGraph()) // writeObject and getProperties depend on each other circularly @@ -664,7 +665,7 @@ export async function getVerifiableCredentialFromStore( // eslint-disable-next-line no-fallthrough case "NamedNode": case "Literal": - return Util.termToValue(object, context); + return Util.termToValue(object, vcContext); default: throw new Error(`Unexpected term type: ${object.termType}`); } @@ -672,10 +673,7 @@ export async function getVerifiableCredentialFromStore( const credentialSubjectTerm = getSingleObjectOfTermType(CREDENTIAL_SUBJECT); return { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://schema.inrupt.com/credentials/v1.jsonld", - ], + "@context": context, id: vc.value, // It is possible to have multiple claims in a credential subject // we do not support this diff --git a/src/parser/contexts/index.ts b/src/parser/contexts/index.ts index 5703114f..10e032d9 100644 --- a/src/parser/contexts/index.ts +++ b/src/parser/contexts/index.ts @@ -21,7 +21,10 @@ import VC from "./vc"; import Inrupt from "./inrupt"; -export default { +const contextDefinitions = { "https://www.w3.org/2018/credentials/v1": VC, "https://schema.inrupt.com/credentials/v1.jsonld": Inrupt, } as const; + +export const context = Object.keys(contextDefinitions); +export default contextDefinitions; From 826ac49c95c9039cfaf548d4dab32f1ceb14b314 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 13:47:49 +1000 Subject: [PATCH 14/35] chore: make remaining IRI templates constants --- src/common/common.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 3532b09d..3323ad53 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -475,6 +475,9 @@ const CREDENTIAL_SUBJECT = `${CRED}credentialSubject`; const ISSUER = `${CRED}issuer`; const ISSUANCE_DATE = `${CRED}issuanceDate`; const PROOF = `${SEC}proof`; +const PROOF_PURPOSE = `${SEC}proofPurpose`; +const VERIFICATION_METHOD = `${SEC}verificationMethod`; +const PROOF_VALUE = `${SEC}proofValue`; /** * @hidden @@ -692,7 +695,7 @@ export async function getVerifiableCredentialFromStore( proofGraph ), proofPurpose: getSingleObjectOfTermType( - `${SEC}proofPurpose`, + PROOF_PURPOSE, proof, proofGraph, "NamedNode", @@ -700,14 +703,14 @@ export async function getVerifiableCredentialFromStore( ), type: proofType, verificationMethod: getSingleObjectOfTermType( - `${SEC}verificationMethod`, + VERIFICATION_METHOD, proof, proofGraph, "NamedNode", proofContext ), proofValue: getSingleObjectOfTermType( - `${SEC}proofValue`, + PROOF_VALUE, proof, proofGraph, "Literal" From f8906e733cb928907c4917d35bc80838483455f7 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 4 Aug 2023 14:06:07 +1000 Subject: [PATCH 15/35] chore: fix lint errors --- src/common/common.test.ts | 9 +++++++++ src/common/common.ts | 3 --- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index e411611c..90b7db43 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -27,6 +27,7 @@ import type { VerifiableCredential } from "./common"; import { concatenateContexts, getVerifiableCredential, + getVerifiableCredentialFromResponse, getVerifiableCredentialFromStore, isVerifiableCredential, isVerifiablePresentation, @@ -1178,3 +1179,11 @@ describe("getVerifiableCredential", () => { ); }); }); + +describe("getVerifiableCredentialFromResponse", () => { + it("should error if the response has no content type", () => { + return expect( + getVerifiableCredentialFromResponse(new Response(), "https://example.org") + ).rejects.toThrow("Response does not have a Content-Type"); + }); +}); diff --git a/src/common/common.ts b/src/common/common.ts index 3323ad53..4d500696 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -417,9 +417,6 @@ function validateVcResponse(response: Response, vcUrl: string): Response { } const contentType = response.headers.get("Content-Type"); - - // Ignoring since the test suite always adds a content type - /* istanbul ignore if */ if (!contentType) { throw new Error( `Fetching the Verifiable Credential [${vcUrl}] failed: Response does not have a Content-Type header; expected application/ld+json` From 6dfafd8c35c7a85a71eab05fc5b6463f3767de71 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Mon, 21 Aug 2023 19:19:33 +1000 Subject: [PATCH 16/35] chore: fix lockfile --- package-lock.json | 6945 +-------------------------------------------- 1 file changed, 1 insertion(+), 6944 deletions(-) diff --git a/package-lock.json b/package-lock.json index 189922e2..d9165145 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,8 +35,8 @@ "eslint": "^8.18.0", "jest": "^29.3.0", "jest-environment-jsdom": "^29.3.0", - "rdf-isomorphic": "^1.3.1", "prettier": "^3.0.2", + "rdf-isomorphic": "^1.3.1", "rollup": "^3.1.0", "rollup-plugin-typescript2": "^0.35.0", "ts-jest": "^29.0.3", @@ -1930,21 +1930,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/lodash": { - "version": "4.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", - "dev": true - }, - "node_modules/@types/lodash.clonedeep": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.7.tgz", - "integrity": "sha512-ccNqkPptFIXrpVqUECi60/DFxjNKsfoQxSQsgcBJCX/fuX1wgyQieojkcWH/KpE3xzLoWN/2k+ZeGqIN3paSvw==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/n3": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/@types/n3/-/n3-1.16.0.tgz", @@ -9740,6933 +9725,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.20.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz", - "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", - "dev": true - }, - "@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "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 - } - } - }, - "@babel/generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", - "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", - "dev": true, - "requires": { - "@babel/types": "^7.20.7", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "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-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "requires": { - "@babel/types": "^7.20.2" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", - "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", - "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "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": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "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" - } - } - } - }, - "@babel/parser": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", - "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/traverse": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", - "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "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.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@bergos/jsonparse": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@bergos/jsonparse/-/jsonparse-1.4.1.tgz", - "integrity": "sha512-vXIT0nzZGX/+yMD5bx2VhTzc92H55tPoehh1BW/FZHOndWGFddrH3MAfdx39FRc7irABirW6EQaGxIJYV6CGuA==", - "requires": { - "buffer": "^6.0.3" - } - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@eslint-community/eslint-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", - "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@inrupt/eslint-config-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@inrupt/eslint-config-base/-/eslint-config-base-2.0.2.tgz", - "integrity": "sha512-aRCv4G8RwWdTfylNKZvwvXG6ZuwRAlnGord1wxXa/oKgrQ8a0YFQDs25PUhxntiWrShxDv4EbIkRnq6zJKXagQ==", - "dev": true, - "requires": { - "eslint": ">=8.43.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-header": "^3.1.1", - "eslint-plugin-import": "^2.20.2", - "eslint-plugin-jest": "^27.1.5", - "eslint-plugin-playwright": "^0.11.2", - "eslint-plugin-prettier": "^4.2.1", - "jest": ">=26.0.0", - "prettier": ">=2.7.1" - } - }, - "@inrupt/eslint-config-lib": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@inrupt/eslint-config-lib/-/eslint-config-lib-2.0.2.tgz", - "integrity": "sha512-nhJODZlZM+DhtJdCEcefnDQabov4wBx0JjrE45pP+49rtkM2c9agDbj2yh1A0APEnABkxhbAMXoJeF7GHg40Ug==", - "dev": true, - "requires": { - "@inrupt/eslint-config-base": "^2.0.2", - "@typescript-eslint/eslint-plugin": "^5.59.11", - "@typescript-eslint/parser": "^5.59.11", - "typescript": ">=5.1.3" - } - }, - "@inrupt/internal-playwright-helpers": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@inrupt/internal-playwright-helpers/-/internal-playwright-helpers-2.1.0.tgz", - "integrity": "sha512-bKWdIUcDt9IdYgUPWsrbn+lCCOgFJWP9knQCiMqd4G+/t/Ta0vTwS9sU7i/vPHZt0u1YeK3VjbRrX5QO70XivQ==", - "dev": true, - "requires": { - "@inrupt/internal-playwright-testids": "2.1.0", - "@inrupt/internal-test-env": "2.1.0" - } - }, - "@inrupt/internal-playwright-testids": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@inrupt/internal-playwright-testids/-/internal-playwright-testids-2.1.0.tgz", - "integrity": "sha512-qKaLCi3Z0K0oUqao9bl+xpAqX9bOkPcDEbDRhuSI6DdDE/d+dOPk5mM5EiPMAX4yBhanH5q+XXk+v1OHdkYkXg==", - "dev": true - }, - "@inrupt/internal-test-env": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@inrupt/internal-test-env/-/internal-test-env-2.1.0.tgz", - "integrity": "sha512-IhlLJfNvX2Mo+jHcxfVxEMTzh1WuM5JVWHTBK4InrFB6L0fjKBMVC2ETKX92Q2A4c9yFYeaKRqVKPjiYZVcmrA==", - "dev": true, - "requires": { - "@inrupt/solid-client": "^1.29.0", - "@inrupt/solid-client-authn-browser": "^1.16.0", - "@inrupt/solid-client-authn-node": "^1.16.0", - "@jeswr/css-auth-utils": "^1.4.0", - "deepmerge-json": "^1.5.0", - "dotenv": "^16.3.1" - }, - "dependencies": { - "dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "dev": true - } - } - }, - "@inrupt/jest-jsdom-polyfills": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@inrupt/jest-jsdom-polyfills/-/jest-jsdom-polyfills-2.1.1.tgz", - "integrity": "sha512-szicQ9uGGYX524Xi+M6ty1BfAwIw8S2fqO3ghpZVUKAKPTisaydHpIEFTP9RLoJzMqS7q5f7xlu8fGIWkMnEZQ==", - "dev": true, - "requires": { - "@peculiar/webcrypto": "^1.4.0", - "@web-std/blob": "^3.0.4", - "@web-std/file": "^3.0.2", - "undici": "^5.22.1" - } - }, - "@inrupt/oidc-client": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@inrupt/oidc-client/-/oidc-client-1.11.6.tgz", - "integrity": "sha512-1rCTk1T6pdm/7gKozutZutk7jwmYBADlnkGGoI5ypke099NOCa5KFXjkQpbjsps0PRkKZ+0EaR70XN5+xqmViA==", - "dev": true, - "requires": { - "acorn": "^7.4.1", - "base64-js": "^1.5.1", - "core-js": "^3.8.3", - "crypto-js": "^4.0.0", - "serialize-javascript": "^4.0.0" - } - }, - "@inrupt/oidc-client-ext": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@inrupt/oidc-client-ext/-/oidc-client-ext-1.16.0.tgz", - "integrity": "sha512-09fJEX64GFq6eWY5xSFsKWo9Uz2v14s2L2It49/KnzAe7O9hc8XXelNndLPxrrOOzuf38YHv4W1irFJPy4PPMw==", - "dev": true, - "requires": { - "@inrupt/oidc-client": "^1.11.6", - "@inrupt/solid-client-authn-core": "^1.16.0", - "jose": "^4.10.0", - "uuid": "^9.0.0" - } - }, - "@inrupt/solid-client": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@inrupt/solid-client/-/solid-client-1.29.0.tgz", - "integrity": "sha512-n5kspeQnrj2h57q4q14bnzC64yPZ/1Y+nvkKy6hamurzsxuRNN/D3tpNjRN4QSTfIE7Yi/swUhu7q5NZ6uASgg==", - "requires": { - "@inrupt/universal-fetch": "^1.0.1", - "@rdfjs/dataset": "^1.1.0", - "@types/rdfjs__dataset": "^1.0.4", - "buffer": "^6.0.3", - "fsevents": "^2.3.2", - "http-link-header": "^1.1.0", - "jsonld-context-parser": "^2.3.0", - "jsonld-streaming-parser": "^3.2.0", - "n3": "^1.10.0", - "uuid": "^9.0.0" - }, - "dependencies": { - "@rdfjs/dataset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@rdfjs/dataset/-/dataset-1.1.1.tgz", - "integrity": "sha512-BNwCSvG0cz0srsG5esq6CQKJc1m8g/M0DZpLuiEp0MMpfwguXX7VeS8TCg4UUG3DV/DqEvhy83ZKSEjdsYseeA==", - "requires": { - "@rdfjs/data-model": "^1.2.0" - } - }, - "@types/rdfjs__dataset": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/rdfjs__dataset/-/rdfjs__dataset-1.0.5.tgz", - "integrity": "sha512-8OBC9Kr/ZSgNoUTe5mHTDPHaPt8Xen4XbYfqcbYv56d+4WdKliHXaFmFc0L4I5vsynE5JGu21Hvg2zWgX1Az6Q==", - "requires": { - "rdf-js": "^4.0.2" - } - } - } - }, - "@inrupt/solid-client-authn-browser": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-browser/-/solid-client-authn-browser-1.16.0.tgz", - "integrity": "sha512-6Wq/e8C5RapSFTRhs7TKThwhLaQ2DdMqmAiqaNlP7XpTWKRv87Chc2sX0msPjzmM+L/Tde2+71lX1o0x6sQbKA==", - "dev": true, - "requires": { - "@inrupt/oidc-client-ext": "^1.16.0", - "@inrupt/solid-client-authn-core": "^1.16.0", - "@inrupt/universal-fetch": "^1.0.1", - "@types/lodash.clonedeep": "^4.5.6", - "@types/node": "^20.1.0", - "@types/uuid": "^9.0.1", - "events": "^3.3.0", - "jose": "^4.3.7", - "lodash.clonedeep": "^4.5.0", - "uuid": "^9.0.0" - } - }, - "@inrupt/solid-client-authn-core": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-core/-/solid-client-authn-core-1.16.0.tgz", - "integrity": "sha512-lp4p21Ob0SJwPW2mJcUkM6YBp/zj9MM+RlHRM1uUdpPgvybGDLEIgJfKjkjku0RqFFJwCSP/KtbdCgnNFk5KXw==", - "dev": true, - "requires": { - "@inrupt/universal-fetch": "^1.0.1", - "events": "^3.3.0", - "jose": "^4.10.0", - "lodash.clonedeep": "^4.5.0", - "uuid": "^9.0.0" - } - }, - "@inrupt/solid-client-authn-node": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@inrupt/solid-client-authn-node/-/solid-client-authn-node-1.16.0.tgz", - "integrity": "sha512-4LSYwMwNUFoXDnwVQ9sxXnMsZCLArcUiYBnCO/PxmeRIkzhGx37RMxUSpGXc26XwhJ4vGHIlbPsdjBxtrpFg9Q==", - "dev": true, - "requires": { - "@inrupt/solid-client-authn-core": "^1.16.0", - "@inrupt/universal-fetch": "^1.0.1", - "jose": "^4.3.7", - "openid-client": "^5.1.0", - "uuid": "^9.0.0" - } - }, - "@inrupt/universal-fetch": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@inrupt/universal-fetch/-/universal-fetch-1.0.1.tgz", - "integrity": "sha512-oqbG7jS1fa6hVkjSir+u5Ab3eSbyxFyOjsgjDICL27mAd5z8oImTSETnY2hYbkRaJQYKMBOXhtm7L5/+EbeVJg==", - "requires": { - "node-fetch": "^2.6.7", - "undici": "^5.19.1" - } - }, - "@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": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "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/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", - "dev": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0" - } - }, - "@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", - "dev": true, - "requires": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" - } - }, - "@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3" - } - }, - "@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" - } - }, - "@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - } - }, - "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.25.16" - } - }, - "@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.15", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", - "dev": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", - "dev": true, - "requires": { - "@jest/test-result": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", - "dev": true, - "requires": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@jeswr/css-auth-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@jeswr/css-auth-utils/-/css-auth-utils-1.4.0.tgz", - "integrity": "sha512-5T/3F63A08fKSowWyvkFqUll2EYoyYiF3ytb3hVbZdi1PtoXInCsBHqTfNy0VaJ3shnZNUbYc6vADfV96gsWxQ==", - "dev": true, - "requires": { - "@inrupt/solid-client-authn-core": "^1.13.0", - "@inrupt/solid-client-authn-node": "^1.13.0", - "cross-fetch": "^3.1.5", - "express": "^4.18.2", - "get-port-please": "^3.0.1", - "puppeteer": "^20.7.1" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@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, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@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 - }, - "@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, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@peculiar/asn1-schema": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz", - "integrity": "sha512-6GptMYDMyWBHTUKndHaDsRZUO/XMSgIns2krxcm2L7SEExRHwawFvSwNBhqNPR9HJwv3MruAiF1bhN0we6j6GQ==", - "dev": true, - "requires": { - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.2", - "tslib": "^2.4.0" - } - }, - "@peculiar/json-schema": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", - "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", - "dev": true, - "requires": { - "tslib": "^2.0.0" - } - }, - "@peculiar/webcrypto": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.1.tgz", - "integrity": "sha512-eK4C6WTNYxoI7JOabMoZICiyqRRtJB220bh0Mbj5RwRycleZf9BPyZoxsTvpP0FpmVS2aS13NKOuh5/tN3sIRw==", - "dev": true, - "requires": { - "@peculiar/asn1-schema": "^2.3.0", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.2", - "tslib": "^2.4.1", - "webcrypto-core": "^1.7.4" - } - }, - "@playwright/test": { - "version": "1.36.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.36.1.tgz", - "integrity": "sha512-YK7yGWK0N3C2QInPU6iaf/L3N95dlGdbsezLya4n0ZCh3IL7VgPGxC6Gnznh9ApWdOmkJeleT2kMTcWPRZvzqg==", - "dev": true, - "requires": { - "@types/node": "*", - "fsevents": "2.3.2", - "playwright-core": "1.36.1" - } - }, - "@puppeteer/browsers": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.2.tgz", - "integrity": "sha512-5MLU1RFaJh1Beb9FH6raowtZErcsZ0ojYJvdG3OWXfnc3wZiDAa0PgXU2QOKtbW2S+Z731K/2n3YczGA3KbLbQ==", - "dev": true, - "requires": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "progress": "2.0.3", - "proxy-agent": "6.2.1", - "tar-fs": "3.0.2", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.1" - } - }, - "@rdfjs/data-model": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@rdfjs/data-model/-/data-model-1.3.4.tgz", - "integrity": "sha512-iKzNcKvJotgbFDdti7GTQDCYmL7GsGldkYStiP0K8EYtN7deJu5t7U11rKTz+nR7RtesUggT+lriZ7BakFv8QQ==", - "requires": { - "@rdfjs/types": ">=1.0.1" - } - }, - "@rdfjs/dataset": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rdfjs/dataset/-/dataset-2.0.1.tgz", - "integrity": "sha512-hDIaXpUmU/ZdofX/BMFDAchkhN/AjmP5dMCOuVL2VCqWuFjeQxd2KV84E4+7S2Biw8tjEFhPBeQZP7KW+ARV7Q==", - "dev": true - }, - "@rdfjs/types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rdfjs/types/-/types-1.1.0.tgz", - "integrity": "sha512-5zm8bN2/CC634dTcn/0AhTRLaQRjXDZs3QfcAsQKNturHT7XVWcKy/8p3P5gXl+YkZTAmy7T5M/LyiT/jbkENw==", - "requires": { - "@types/node": "*" - } - }, - "@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "requires": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - } - }, - "@rushstack/eslint-patch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz", - "integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==", - "dev": true - }, - "@sinclair/typebox": { - "version": "0.25.21", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.21.tgz", - "integrity": "sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==", - "dev": true - }, - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0" - } - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/content-type": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.5.tgz", - "integrity": "sha512-dgMN+syt1xb7Hk8LU6AODOfPlvz5z1CbXpPuJE5ZrX9STfBOIXF09pEB8N7a97WT9dbngt3ksDCm6GW6yMrxfQ==", - "dev": true - }, - "@types/dotenv-flow": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@types/dotenv-flow/-/dotenv-flow-3.2.0.tgz", - "integrity": "sha512-A79hbPwocbYkcTwGcDOFbKDuqyVo5mLAz/6Iq465YZ7R7Go5bT1PIM8I2jlPQkaD9u9fbotGVLkUPhX+9XUHfw==", - "dev": true - }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/http-link-header": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/http-link-header/-/http-link-header-1.0.3.tgz", - "integrity": "sha512-y8HkoD/vyid+5MrJ3aas0FvU3/BVBGcyG9kgxL0Zn4JwstA8CglFPnrR0RuzOjRCXwqzL5uxWC2IO7Ub0rMU2A==", - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "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/jest": { - "version": "29.5.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", - "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", - "dev": true, - "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, - "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "@types/lodash": { - "version": "4.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", - "dev": true - }, - "@types/lodash.clonedeep": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.7.tgz", - "integrity": "sha512-ccNqkPptFIXrpVqUECi60/DFxjNKsfoQxSQsgcBJCX/fuX1wgyQieojkcWH/KpE3xzLoWN/2k+ZeGqIN3paSvw==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, - "@types/n3": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@types/n3/-/n3-1.16.0.tgz", - "integrity": "sha512-g/67NVSihmIoIZT3/J462NhJrmpCw+5WUkkKqpCE9YxNEWzBwKavGPP+RUmG6DIm5GrW4GPunuxLJ0Yn/GgNjQ==", - "dev": true, - "requires": { - "@rdfjs/types": "^1.1.0", - "@types/node": "*" - } - }, - "@types/node": { - "version": "20.4.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.5.tgz", - "integrity": "sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg==" - }, - "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "@types/rdfjs__dataset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/rdfjs__dataset/-/rdfjs__dataset-2.0.3.tgz", - "integrity": "sha512-VjdsE3qkeZBXij24lsN/Revdf6lQsyTBK1SYgNbixrt/8RHMrNGtLfH8WAXAnxtC7lCJJ7+CUmpuhwEVDwIvLA==", - "dev": true, - "requires": { - "@rdfjs/types": "*" - } - }, - "@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", - "requires": { - "@types/node": "*", - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "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==" - } - } - }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "@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 - }, - "@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "@types/uuid": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", - "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", - "dev": true - }, - "@types/yargs": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", - "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.0.tgz", - "integrity": "sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/type-utils": "5.60.0", - "@typescript-eslint/utils": "5.60.0", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.0.tgz", - "integrity": "sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", - "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.0.tgz", - "integrity": "sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.60.0", - "@typescript-eslint/utils": "5.60.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", - "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", - "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", - "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", - "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.60.0", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@web-std/blob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@web-std/blob/-/blob-3.0.4.tgz", - "integrity": "sha512-+dibyiw+uHYK4dX5cJ7HA+gtDAaUUe6JsOryp2ZpAC7h4ICsh49E34JwHoEKPlPvP0llCrNzz45vvD+xX5QDBg==", - "dev": true, - "requires": { - "@web-std/stream": "1.0.0", - "web-encoding": "1.1.5" - } - }, - "@web-std/file": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@web-std/file/-/file-3.0.2.tgz", - "integrity": "sha512-pIH0uuZsmY8YFvSHP1NsBIiMT/1ce0suPrX74fEeO3Wbr1+rW0fUGEe4d0R99iLwXtyCwyserqCFI4BJkJlkRA==", - "dev": true, - "requires": { - "@web-std/blob": "^3.0.3" - } - }, - "@web-std/stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@web-std/stream/-/stream-1.0.0.tgz", - "integrity": "sha512-jyIbdVl+0ZJyKGTV0Ohb9E6UnxP+t7ZzX4Do3AHjZKxUXKMs9EmqnBDQgHF7bEw0EzbQygOjtt/7gvtmi//iCQ==", - "dev": true, - "requires": { - "web-streams-polyfill": "^3.1.1" - } - }, - "@zxing/text-encoding": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", - "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", - "dev": true, - "optional": true - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, - "requires": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" - }, - "dependencies": { - "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true - } - } - }, - "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, - "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 - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "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 - }, - "ansi-sequence-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", - "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" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "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 - }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - } - }, - "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 - }, - "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "asn1js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", - "dev": true, - "requires": { - "pvtsutils": "^1.3.2", - "pvutils": "^1.1.3", - "tslib": "^2.4.0" - } - }, - "ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "requires": { - "tslib": "^2.0.1" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "b4a": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", - "dev": true - }, - "babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", - "dev": true, - "requires": { - "@jest/transform": "^29.5.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "basic-ftp": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", - "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", - "dev": true - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.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" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "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" - } - }, - "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true - }, - "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==", - "dev": true - }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "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, - "requires": { - "function-bind": "^1.1.1", - "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==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001441", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz", - "integrity": "sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==", - "dev": true - }, - "canonicalize": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", - "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==" - }, - "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" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chromium-bidi": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.12.tgz", - "integrity": "sha512-yl0ngMHtYUGJa2G0lkcbPvbnUZ9WMQyMNSfYmlrGD1nHRNyI9KOGw3dOaofFugXHHToneUaSmF9iUdgCBamCjA==", - "dev": true, - "requires": { - "mitt": "3.0.0" - } - }, - "ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "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, - "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 - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "core-js": { - "version": "3.31.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.31.0.tgz", - "integrity": "sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ==", - "dev": true - }, - "cosmiconfig": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", - "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", - "dev": true, - "requires": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - } - }, - "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 - }, - "cross-fetch": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", - "integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==", - "requires": { - "node-fetch": "^2.6.11" - } - }, - "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" - } - }, - "crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==", - "dev": true - }, - "cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-uri-to-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", - "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", - "dev": true - }, - "data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "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 - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true - }, - "deepmerge-json": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/deepmerge-json/-/deepmerge-json-1.5.0.tgz", - "integrity": "sha512-jZRrDmBKjmGcqMFEUJ14FjMJwm05Qaked+1vxaALRtF0UAl7lPU8OLWXFxvoeg3jbQM249VPFVn8g2znaQkEtA==", - "dev": true - }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "degenerator": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-4.0.3.tgz", - "integrity": "sha512-2wY8vmCfxrQpe2PKGYdiWRre5HQRwsAXbAAWRbC+z2b80MEpnWc8A3a9k4TwqwN3Z/Fm3uhNm5vYUZIbMhyRxQ==", - "dev": true, - "requires": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0", - "vm2": "^3.9.19" - }, - "dependencies": { - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true - }, - "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 - }, - "devtools-protocol": { - "version": "0.0.1135028", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1135028.tgz", - "integrity": "sha512-jEcNGrh6lOXNRJvZb9RjeevtZGrgugPKSMJZxfyxWQnhlKawMPhMtk/dfC+Z/6xNXExlzTKlY5LzIAK/fRpQIw==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true - }, - "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, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "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" - } - }, - "domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "requires": { - "webidl-conversions": "^7.0.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "dev": true - }, - "dotenv-flow": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/dotenv-flow/-/dotenv-flow-3.2.0.tgz", - "integrity": "sha512-GEB6RrR4AbqDJvNSFrYHqZ33IKKbzkvLYiD5eo4+9aFXr4Y4G+QaFrB/fNp0y6McWBmvaPn3ZNjIufnj8irCtg==", - "dev": true, - "requires": { - "dotenv": "^8.0.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "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==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - } - }, - "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - } - }, - "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "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 - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "requires": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "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 - } - } - }, - "eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-header": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz", - "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==", - "dev": true, - "requires": {} - }, - "eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "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" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "eslint-plugin-jest": { - "version": "27.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz", - "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "^5.10.0" - } - }, - "eslint-plugin-playwright": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.11.2.tgz", - "integrity": "sha512-uRLRLk7uTzc8NE6t4wBU8dijQwHvC66R/h7xwdM779jsJjMUtSmeaB8ayRkkpfwi+UU5BEfwvDANwmE+ccMVDw==", - "dev": true, - "requires": {} - }, - "eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "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, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "dependencies": { - "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true - } - } - }, - "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 - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "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, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true - }, - "event-emitter-promisify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/event-emitter-promisify/-/event-emitter-promisify-1.1.0.tgz", - "integrity": "sha512-uyHG8gjwYGDlKoo0Txtx/u1HI1ubj0FK0rVqI4O0s1EymQm4iAEMbrS5B+XFlSaS8SZ3xzoKX+YHRZk8Nk/bXg==" - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true - }, - "expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.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==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } - } - }, - "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==", - "dev": true - }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "fast-fifo": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.2.0.tgz", - "integrity": "sha512-NcvQXt7Cky1cNau15FWy64IjuO8X0JijhTBBrJj1YlxlDfRkJXNaK9RFUjwpfDPzMdv7wB38jr53l9tkNLxnWg==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@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" - }, - "dependencies": { - "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, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "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, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "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, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "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, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "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" - } - }, - "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.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "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 - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "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 - }, - "get-port-please": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.0.1.tgz", - "integrity": "sha512-R5pcVO8Z1+pVDu8Ml3xaJCEkBiiy1VQN9za0YqH8GIi1nIqD4IzQhzY6dDzMRtdS1lyiGlucRzm8IN8wtLIXng==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "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" - } - }, - "get-uri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", - "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", - "dev": true, - "requires": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^5.0.1", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "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": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "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==", - "dev": true - } - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "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, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "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 - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "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" - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", - "dev": true, - "requires": { - "whatwg-encoding": "^2.0.0" - } - }, - "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 - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "http-link-header": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.1.0.tgz", - "integrity": "sha512-pj6N1yxOz/ANO8HHsWGg/OoIL1kmRYvQnXQ7PIRpgp+15AnEsRH8fmIJE6D1OdWG2Bov+BJHVla1fFXxg1JbbA==" - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "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, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "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-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-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "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, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "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 - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "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, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "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==", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "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, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "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.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.2" - } - }, - "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.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 - } - } - }, - "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" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", - "dev": true, - "requires": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", - "import-local": "^3.0.2", - "jest-cli": "^29.5.0" - } - }, - "jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "requires": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - } - }, - "jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", - "dev": true, - "requires": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - } - }, - "jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - } - }, - "jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" - } - }, - "jest-environment-jsdom": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.5.0.tgz", - "integrity": "sha512-/KG8yEK4aN8ak56yFVdqFDzKNHgF4BAymCx2LbPNPsUshUlfAl0eX402Xm1pt+eoG9SLZEUVifqXtX8SK74KCw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0", - "jsdom": "^20.0.0" - } - }, - "jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", - "dev": true - }, - "jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", - "dev": true, - "requires": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - } - }, - "jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - } - }, - "jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-util": "^29.5.0" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true - }, - "jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", - "dev": true, - "requires": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" - } - }, - "jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", - "dev": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - } - }, - "jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" - } - }, - "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "leven": "^3.1.0", - "pretty-format": "^29.5.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", - "dev": true, - "requires": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.5.0", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "jose": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", - "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsdom": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "acorn": "^8.8.1", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.2", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.11.0", - "xml-name-validator": "^4.0.0" - }, - "dependencies": { - "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true - } - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "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 - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-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": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "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==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonld-context-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/jsonld-context-parser/-/jsonld-context-parser-2.3.0.tgz", - "integrity": "sha512-c6w2GE57O26eWFjcPX6k6G86ootsIfpuVwhZKjCll0bVoDGBxr1P4OuU+yvgfnh1GJhAGErolfC7W1BklLjWMg==", - "requires": { - "@types/http-link-header": "^1.0.1", - "@types/node": "^18.0.0", - "canonicalize": "^1.0.1", - "cross-fetch": "^3.0.6", - "http-link-header": "^1.0.2", - "relative-to-absolute-iri": "^1.0.5" - }, - "dependencies": { - "@types/node": { - "version": "18.16.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.7.tgz", - "integrity": "sha512-MFg7ua/bRtnA1hYE3pVyWxGd/r7aMqjNOdHvlSsXV3n8iaeGKkOaPzpJh6/ovf4bEXWcojkeMJpTsq3mzXW4IQ==" - } - } - }, - "jsonld-streaming-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonld-streaming-parser/-/jsonld-streaming-parser-3.2.0.tgz", - "integrity": "sha512-lJR1SCT364PGpFrOQaY+ZQ7qDWqqiT3IMK+AvZ83fo0LvltFn8/UyXvIFc3RO7YcaEjLahAF0otCi8vOq21NtQ==", - "requires": { - "@bergos/jsonparse": "^1.4.0", - "@rdfjs/types": "*", - "@types/http-link-header": "^1.0.1", - "@types/readable-stream": "^2.3.13", - "buffer": "^6.0.3", - "canonicalize": "^1.0.1", - "http-link-header": "^1.0.2", - "jsonld-context-parser": "^2.3.0", - "rdf-data-factory": "^1.1.0", - "readable-stream": "^4.0.0" - } - }, - "jsonld-streaming-serializer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/jsonld-streaming-serializer/-/jsonld-streaming-serializer-2.1.0.tgz", - "integrity": "sha512-COHdLoeMTnrqHMoFhN3PoAwqnrKrpPC7/ACb0WbELYvt+HSOIFN3v4IJP7fOtLNQ4GeaeYkvbeWJ7Jo4EjxMDw==", - "requires": { - "@rdfjs/types": "*", - "@types/readable-stream": "^2.3.13", - "buffer": "^6.0.3", - "jsonld-context-parser": "^2.0.0", - "readable-stream": "^4.0.0" - } - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.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.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "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" - } - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "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 - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "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" - }, - "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 - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true - }, - "mitt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", - "dev": true - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "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 - }, - "n3": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/n3/-/n3-1.17.0.tgz", - "integrity": "sha512-dYdkyUM4tMWHSEf9xMDPiBjOJc+rcjZHtN5cJJGcvAwOWTjE9u1i28sDFWALTwyROvsuUKuLohrz7VFaJbhiDw==", - "requires": { - "queue-microtask": "^1.1.2", - "readable-stream": "^4.0.0" - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "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 - }, - "netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true - }, - "node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "requires": { - "whatwg-url": "^5.0.0" - }, - "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", - "dev": true - }, - "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 - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nwsapi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", - "dev": true - }, - "object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "dev": true - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "oidc-token-hash": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", - "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "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, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "openid-client": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.4.2.tgz", - "integrity": "sha512-lIhsdPvJ2RneBm3nGBBhQchpe3Uka//xf7WPHTIglery8gnckvW7Bd9IaQzekzXJvWthCMyi/xVEyGW0RFPytw==", - "dev": true, - "requires": { - "jose": "^4.14.1", - "lru-cache": "^6.0.0", - "object-hash": "^2.2.0", - "oidc-token-hash": "^5.0.3" - }, - "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==", - "dev": true, - "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==", - "dev": true - } - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "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" - } - }, - "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 - }, - "pac-proxy-agent": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-6.0.3.tgz", - "integrity": "sha512-5Hr1KgPDoc21Vn3rsXBirwwDnF/iac1jN/zkpsOYruyT+ZgsUhUOgVwq3v9+ukjZd/yGm/0nzO1fDfl7rkGoHQ==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "pac-resolver": "^6.0.1", - "socks-proxy-agent": "^8.0.1" - }, - "dependencies": { - "agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.0.tgz", - "integrity": "sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - } - } - }, - "pac-resolver": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-6.0.1.tgz", - "integrity": "sha512-dg497MhVT7jZegPRuOScQ/z0aV/5WR0gTdRu1md+Irs9J9o+ls5jIuxjo1WfaTG+eQQkxyn5HMGvWK+w7EIBkQ==", - "dev": true, - "requires": { - "degenerator": "^4.0.1", - "ip": "^1.1.5", - "netmask": "^2.0.2" - } - }, - "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, - "requires": { - "callsites": "^3.0.0" - } - }, - "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" - } - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "requires": { - "entities": "^4.4.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "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 - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "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.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": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "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==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "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" - }, - "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" - } - } - } - }, - "playwright-core": { - "version": "1.36.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.36.1.tgz", - "integrity": "sha512-7+tmPuMcEW4xeCL9cp9KxmYpQYHKkyjwoXRnoeTowaeNat8PoBMk/HwCYhqkH2fRkshfKEOiVus/IhID2Pg8kg==", - "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==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "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" - } - }, - "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "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==", - "dev": true - } - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.2.1.tgz", - "integrity": "sha512-OIbBKlRAT+ycCm6wAYIzMwPejzRtjy8F3QiDX0eKOA3e4pe3U9F/IvzcHP42bmgQxVv97juG+J8/gx+JIeCX/Q==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^6.0.3", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.1" - }, - "dependencies": { - "agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.0.tgz", - "integrity": "sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true - } - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "puppeteer": { - "version": "20.7.3", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-20.7.3.tgz", - "integrity": "sha512-3tw12ykFRLvzTRc9PyUOE5xeHQhhLEcKEOVjSfNtRmZqlAnvfhAP8ue+mjojy8NJ1LIfF6fps7OKzSc4JSJSlA==", - "dev": true, - "requires": { - "@puppeteer/browsers": "1.4.2", - "cosmiconfig": "8.2.0", - "puppeteer-core": "20.7.3" - } - }, - "puppeteer-core": { - "version": "20.7.3", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.7.3.tgz", - "integrity": "sha512-OraI71GPPfUMosLqaOsDGbp/ZLoxLTm0BAda0uE6G+H3onmljfoaJcIPm8X5y1LMq1K1HF1bipcCI7hWGkd3bQ==", - "dev": true, - "requires": { - "@puppeteer/browsers": "1.4.2", - "chromium-bidi": "0.4.12", - "cross-fetch": "3.1.6", - "debug": "4.3.4", - "devtools-protocol": "0.0.1135028", - "ws": "8.13.0" - } - }, - "pure-rand": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", - "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", - "dev": true - }, - "pvtsutils": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", - "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", - "dev": true, - "requires": { - "tslib": "^2.4.0" - } - }, - "pvutils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true - }, - "randombytes": { - "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" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "rdf-data-factory": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/rdf-data-factory/-/rdf-data-factory-1.1.1.tgz", - "integrity": "sha512-0HoLx7lbBlNd2YTmNKin0txgiYmAV56eVU823at8cG2+iD0Ia5kcRNDpzZy6I/HCtFTymHvTfdhHTzm3ak3Jpw==", - "requires": { - "@rdfjs/types": "*" - } - }, - "rdf-isomorphic": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rdf-isomorphic/-/rdf-isomorphic-1.3.1.tgz", - "integrity": "sha512-6uIhsXTVp2AtO6f41PdnRV5xZsa0zVZQDTBdn0br+DZuFf5M/YD+T6m8hKDUnALI6nFL/IujTMLgEs20MlNidQ==", - "dev": true, - "requires": { - "@rdfjs/types": "*", - "hash.js": "^1.1.7", - "rdf-string": "^1.6.0", - "rdf-terms": "^1.7.0" - } - }, - "rdf-js": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/rdf-js/-/rdf-js-4.0.2.tgz", - "integrity": "sha512-ApvlFa/WsQh8LpPK/6hctQwG06Z9ztQQGWVtrcrf9L6+sejHNXLPOqL+w7q3hF+iL0C4sv3AX1PUtGkLNzyZ0Q==", - "requires": { - "@rdfjs/types": "*" - } - }, - "rdf-string": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/rdf-string/-/rdf-string-1.6.3.tgz", - "integrity": "sha512-HIVwQ2gOqf+ObsCLSUAGFZMIl3rh9uGcRf1KbM85UDhKqP+hy6qj7Vz8FKt3GA54RiThqK3mNcr66dm1LP0+6g==", - "dev": true, - "requires": { - "@rdfjs/types": "*", - "rdf-data-factory": "^1.1.0" - } - }, - "rdf-terms": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/rdf-terms/-/rdf-terms-1.11.0.tgz", - "integrity": "sha512-iKlVgnMopRKl9pHVNrQrax7PtZKRCT/uJIgYqvuw1VVQb88zDvurtDr1xp0rt7N9JtKtFwUXoIQoEsjyRo20qQ==", - "dev": true, - "requires": { - "@rdfjs/types": "*", - "rdf-data-factory": "^1.1.0", - "rdf-string": "^1.6.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "readable-stream": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz", - "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10" - } - }, - "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - } - }, - "relative-to-absolute-iri": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/relative-to-absolute-iri/-/relative-to-absolute-iri-1.0.7.tgz", - "integrity": "sha512-Xjyl4HmIzg2jzK/Un2gELqbcE8Fxy85A/aLSHE6PE/3+OGsFwmKVA1vRyGaz6vLWSqLDMHA+5rjD/xbibSQN1Q==" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "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 - } - } - }, - "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 - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.27.0.tgz", - "integrity": "sha512-aOltLCrYZ0FhJDm7fCqwTjIUEVjWjcydKBV/Zeid6Mn8BWgDCUBBWT5beM5ieForYNo/1ZHuGJdka26kvQ3Gzg==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "rollup-plugin-typescript2": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.35.0.tgz", - "integrity": "sha512-szcIO9hPUx3PhQl91u4pfNAH2EKbtrXaES+m163xQVE5O1CC0ea6YZV/5woiDDW3CR9jF2CszPrKN+AFiND0bg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.1.2", - "find-cache-dir": "^3.3.2", - "fs-extra": "^10.0.0", - "semver": "^7.3.7", - "tslib": "^2.4.0" - } - }, - "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, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "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==", - "dev": true - }, - "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true - } - } - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "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" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "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 - } - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "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 - }, - "shiki": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.1.tgz", - "integrity": "sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==", - "dev": true, - "requires": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, - "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", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "dependencies": { - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - } - } - }, - "socks-proxy-agent": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.1.tgz", - "integrity": "sha512-59EjPbbgg8U3x62hhKOFVAmySQUcfRQ4C7Q/D5sEHnZTQRrQlNKINks44DMR1gwXp0p4LaVIeccX2KHTTcHVqQ==", - "dev": true, - "requires": { - "agent-base": "^7.0.1", - "debug": "^4.3.4", - "socks": "^2.7.1" - }, - "dependencies": { - "agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "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 - } - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, - "streamx": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.0.tgz", - "integrity": "sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg==", - "dev": true, - "requires": { - "fast-fifo": "^1.1.0", - "queue-tick": "^1.0.1" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "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" - } - }, - "string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "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, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "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 - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "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": "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" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "tar-fs": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.2.tgz", - "integrity": "sha512-mLQ5iTTCv2tt3a4BwvD8QX1YFVBL/94/Nd+U2il38wt2+zaJSusp1VwJSNkBmB48FeTdOqptf1DAUIosXQBRrQ==", - "dev": true, - "requires": { - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^3.1.0" - } - }, - "tar-stream": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.4.tgz", - "integrity": "sha512-IlHr7ZOW6XaVBCrSCokUJG4IqUuRcWW76B8XbrtCotbaDh6zVGE7WPCzaSz1CN+acFmWiwoa+cE4RZsom0RzXg==", - "dev": true, - "requires": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "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, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "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, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true - }, - "tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "dependencies": { - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true - } - } - }, - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - } - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@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", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "dependencies": { - "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true - } - } - }, - "tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "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": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", - "dev": true - }, - "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" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "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==", - "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==", - "dev": true - }, - "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 - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - } - }, - "typedoc": { - "version": "0.24.8", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", - "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", - "dev": true, - "requires": { - "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.0", - "shiki": "^0.14.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "typedoc-plugin-markdown": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.15.3.tgz", - "integrity": "sha512-idntFYu3vfaY3eaD+w9DeRd0PmNGqGuNLKihPU9poxFGnATJYGn9dPtEhn2QrTdishFMg7jPXAhos+2T6YCWRQ==", - "dev": true, - "requires": { - "handlebars": "^4.7.7" - } - }, - "typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", - "dev": true - }, - "uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, - "optional": true - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - }, - "dependencies": { - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - } - } - }, - "undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", - "requires": { - "busboy": "^1.6.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true - }, - "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - } - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true - }, - "vm2": { - "version": "3.9.19", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.19.tgz", - "integrity": "sha512-J637XF0DHDMV57R6JyVsTak7nIL8gy5KH4r1HiwWLf/4GBbb5MKL5y7LpmF4A8E2nR6XmzpmMFQ7V7ppPTmUQg==", - "dev": true, - "requires": { - "acorn": "^8.7.0", - "acorn-walk": "^8.2.0" - }, - "dependencies": { - "acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", - "dev": true - } - } - }, - "vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, - "w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "requires": { - "xml-name-validator": "^4.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "web-encoding": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", - "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", - "dev": true, - "requires": { - "@zxing/text-encoding": "0.9.0", - "util": "^0.12.3" - } - }, - "web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "dev": true - }, - "webcrypto-core": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.6.tgz", - "integrity": "sha512-TBPiewB4Buw+HI3EQW+Bexm19/W4cP/qZG/02QJCXN+iN+T5sl074vZ3rJcle/ZtDBQSgjkbsQO/1eFcxnSBUA==", - "dev": true, - "requires": { - "@peculiar/asn1-schema": "^2.1.6", - "@peculiar/json-schema": "^1.1.12", - "asn1js": "^3.0.1", - "pvtsutils": "^1.3.2", - "tslib": "^2.4.0" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true - }, - "whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "requires": { - "iconv-lite": "0.6.3" - } - }, - "whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "dev": true, - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.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" - } - }, - "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-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "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" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "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==", - "dev": true - }, - "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "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 - } } } From 7a7fff79f1e0cb01e5bf6f159436101265243749 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Mon, 21 Aug 2023 19:19:49 +1000 Subject: [PATCH 17/35] chore: run lint:fix --- src/common/common.mock.ts | 10 +- src/common/common.test.ts | 223 +++++++++++++++++++------------------- src/common/common.ts | 54 ++++----- src/parser/jsonld.test.ts | 34 +++--- src/parser/jsonld.ts | 4 +- 5 files changed, 164 insertions(+), 161 deletions(-) diff --git a/src/common/common.mock.ts b/src/common/common.mock.ts index 2cade2a5..37372403 100644 --- a/src/common/common.mock.ts +++ b/src/common/common.mock.ts @@ -78,7 +78,7 @@ export const defaultCredentialClaims: CredentialClaims = { export const mockPartialCredential = ( claims?: Partial, - id?: string + id?: string, ): Record => { return { "@context": claims?.["@context"], @@ -102,7 +102,7 @@ export const mockPartialCredential = ( export const mockPartialCredential2Proofs = ( claims?: Partial, - id?: string + id?: string, ): Record => { return { ...mockPartialCredential(claims, id), @@ -122,16 +122,16 @@ export const mockCredential = ( export const mockDefaultCredential = (id?: string): VerifiableCredential => { return mockPartialCredential( defaultCredentialClaims, - id + id, ) as VerifiableCredential; }; export const mockDefaultCredential2Proofs = ( - id?: string + id?: string, ): VerifiableCredential => { return mockPartialCredential2Proofs( defaultCredentialClaims, - id + id, ) as VerifiableCredential; }; diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 0ece48c1..34be1d99 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -274,7 +274,7 @@ describe("getVerifiableCredential", () => { mockedFetchModule.fetch.mockResolvedValueOnce( new Response(JSON.stringify(mockDefaultCredential()), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); const redirectUrl = new URL("https://redirect.url"); @@ -297,7 +297,7 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mockDefaultCredential()), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await getVerifiableCredential("https://some.vc", { @@ -356,7 +356,7 @@ describe("getVerifiableCredential", () => { await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow(/unsupported Content-Type/); }); @@ -366,15 +366,15 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify({}), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - /Expected exactly one Verifiable Credential.* received: 0/ + /Expected exactly one Verifiable Credential.* received: 0/, ); }); @@ -388,16 +388,16 @@ describe("getVerifiableCredential", () => { }), { headers: new Headers([["content-type", "application/json"]]), - } - ) + }, + ), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - "Expected the Verifiable Credential in [https://some.vc] to be a Named Node, received: BlankNode" + "Expected the Verifiable Credential in [https://some.vc] to be a Named Node, received: BlankNode", ); }); @@ -419,16 +419,16 @@ describe("getVerifiableCredential", () => { }), { headers: new Headers([["content-type", "application/json"]]), - } - ) + }, + ), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - "Expected all VC types to be Named Nodes but received [str] of termType [Literal]" + "Expected all VC types to be Named Nodes but received [str] of termType [Literal]", ); }); @@ -443,16 +443,16 @@ describe("getVerifiableCredential", () => { ]), { headers: new Headers([["content-type", "application/json"]]), - } - ) + }, + ), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - /Expected exactly one Verifiable Credential.* received: 2/ + /Expected exactly one Verifiable Credential.* received: 2/, ); }); @@ -462,15 +462,15 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mockDefaultCredential2Proofs()), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - /Expected exactly one \[https:\/\/w3id.org\/security#proof\].* received: 2/ + /Expected exactly one \[https:\/\/w3id.org\/security#proof\].* received: 2/, ); }); @@ -483,15 +483,15 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mocked), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - /Invalid dateTime in VC \[http:\/\/example.org\/not\/a\/date\]/ + /Invalid dateTime in VC \[http:\/\/example.org\/not\/a\/date\]/, ); }); @@ -507,15 +507,15 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mocked), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - /Expected issuanceDate to have dataType \[http:\/\/www.w3.org\/2001\/XMLSchema#dateTime\], received: \[http:\/\/www.w3.org\/2001\/XMLSchema#string\]/ + /Expected issuanceDate to have dataType \[http:\/\/www.w3.org\/2001\/XMLSchema#dateTime\], received: \[http:\/\/www.w3.org\/2001\/XMLSchema#string\]/, ); }); @@ -532,15 +532,15 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mocked), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - /Expected issuanceDate to be a Literal, received: NamedNode/ + /Expected issuanceDate to be a Literal, received: NamedNode/, ); }); @@ -554,15 +554,15 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mocked), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - "Expected property [https://www.w3.org/2018/credentials#issuer] of the Verifiable Credential [https://example.org/ns/someCredentialInstance] to be a NamedNode, received: Literal" + "Expected property [https://www.w3.org/2018/credentials#issuer] of the Verifiable Credential [https://example.org/ns/someCredentialInstance] to be a NamedNode, received: Literal", ); }); @@ -585,12 +585,12 @@ describe("getVerifiableCredential", () => { DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicate"), // @ts-expect-error DefaultGraph is not allowed as an object - DataFactory.defaultGraph() - ) + DataFactory.defaultGraph(), + ), ); await expect( - getVerifiableCredentialFromStore(store, "https://some.vc") + getVerifiableCredentialFromStore(store, "https://some.vc"), ).rejects.toThrow("Unexpected term type: DefaultGraph"); }); @@ -613,12 +613,12 @@ describe("getVerifiableCredential", () => { DataFactory.namedNode("https://some.webid.provider/strelka"), // @ts-expect-error Literal is not allowed as a subject DataFactory.literal("https://example.org/predicate"), - DataFactory.namedNode("https://example.org/ns/object") - ) + DataFactory.namedNode("https://example.org/ns/object"), + ), ); await expect( - getVerifiableCredentialFromStore(store, "https://some.vc") + getVerifiableCredentialFromStore(store, "https://some.vc"), ).rejects.toThrow("Predicate must be a namedNode"); }); @@ -640,7 +640,7 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mocked), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); const vc = await getVerifiableCredential("https://some.vc", { @@ -674,35 +674,35 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("http://example.org/vc"), DataFactory.namedNode("https://w3id.org/security#proof"), - DataFactory.namedNode("http://example.org/proofGraph") + DataFactory.namedNode("http://example.org/proofGraph"), ), DataFactory.quad( DataFactory.namedNode("http://example.org/s"), DataFactory.namedNode("http://example.org/p"), DataFactory.namedNode("http://example.org/o"), - DataFactory.namedNode("http://example.org/proofGraph") + DataFactory.namedNode("http://example.org/proofGraph"), ), DataFactory.quad( DataFactory.namedNode("http://example.org/s2"), DataFactory.namedNode("http://example.org/p2"), DataFactory.namedNode("http://example.org/o2"), - DataFactory.namedNode("http://example.org/proofGraph") + DataFactory.namedNode("http://example.org/proofGraph"), ), DataFactory.quad( DataFactory.namedNode("http://example.org/vc"), DataFactory.namedNode( - "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", ), DataFactory.namedNode( - "https://www.w3.org/2018/credentials#VerifiableCredential" - ) + "https://www.w3.org/2018/credentials#VerifiableCredential", + ), ), ]); await expect( - getVerifiableCredentialFromStore(store, "http://example.org/vc") + getVerifiableCredentialFromStore(store, "http://example.org/vc"), ).rejects.toThrow( - "Expected exactly one proof to live in the proofs graph, received 2" + "Expected exactly one proof to live in the proofs graph, received 2", ); }); @@ -711,35 +711,35 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("http://example.org/vc2"), DataFactory.namedNode("https://w3id.org/security#proof"), - DataFactory.namedNode("http://example.org/proofGraph") + DataFactory.namedNode("http://example.org/proofGraph"), ), DataFactory.quad( DataFactory.namedNode("http://example.org/s"), DataFactory.namedNode("http://example.org/p"), DataFactory.namedNode("http://example.org/o"), - DataFactory.namedNode("http://example.org/proofGraph") + DataFactory.namedNode("http://example.org/proofGraph"), ), DataFactory.quad( DataFactory.namedNode("http://example.org/s2"), DataFactory.namedNode("http://example.org/p2"), DataFactory.namedNode("http://example.org/o2"), - DataFactory.namedNode("http://example.org/proofGraph") + DataFactory.namedNode("http://example.org/proofGraph"), ), DataFactory.quad( DataFactory.namedNode("http://example.org/vc"), DataFactory.namedNode( - "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", ), DataFactory.namedNode( - "https://www.w3.org/2018/credentials#VerifiableCredential" - ) + "https://www.w3.org/2018/credentials#VerifiableCredential", + ), ), ]); await expect( - getVerifiableCredentialFromStore(store, "http://example.org/vc") + getVerifiableCredentialFromStore(store, "http://example.org/vc"), ).rejects.toThrow( - "Expected exactly one [https://w3id.org/security#proof] for the Verifiable Credential http://example.org/vc, received: 0" + "Expected exactly one [https://w3id.org/security#proof] for the Verifiable Credential http://example.org/vc, received: 0", ); }); @@ -753,15 +753,15 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mocked), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); await expect( getVerifiableCredential("https://some.vc", { fetch: mockedFetch, - }) + }), ).rejects.toThrow( - /Expected exactly one \[https:\/\/w3id.org\/security#proofValue\] for the Verifiable Credential https:\/\/example.org\/ns\/someCredentialInstance, received: 2/ + /Expected exactly one \[https:\/\/w3id.org\/security#proofValue\] for the Verifiable Credential https:\/\/example.org\/ns\/someCredentialInstance, received: 2/, ); }); @@ -771,7 +771,7 @@ describe("getVerifiableCredential", () => { .mockResolvedValueOnce( new Response(JSON.stringify(mockDefaultCredential()), { headers: new Headers([["content-type", "application/json"]]), - }) + }), ); const vc = await getVerifiableCredential("https://some.vc", { @@ -779,7 +779,7 @@ describe("getVerifiableCredential", () => { }); const res = await jsonLdStringToStore( - JSON.stringify(mockDefaultCredential()) + JSON.stringify(mockDefaultCredential()), ); expect(vc).toMatchObject( Object.assign(mockDefaultCredential(), { @@ -802,34 +802,34 @@ describe("getVerifiableCredential", () => { }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], - }) + }), ); const meaninglessQuad = DataFactory.quad( DataFactory.namedNode("http://example.org/a"), DataFactory.namedNode("http://example.org/b"), - DataFactory.namedNode("http://example.org/c") + DataFactory.namedNode("http://example.org/c"), ); const issuerQuad = DataFactory.quad( DataFactory.namedNode("https://example.org/ns/someCredentialInstance"), DataFactory.namedNode("https://www.w3.org/2018/credentials#issuer"), - DataFactory.namedNode("https://some.vc.issuer/in-ussr") + DataFactory.namedNode("https://some.vc.issuer/in-ussr"), ); expect(isomorphic([...vc], [...res])).toBe(true); expect(isomorphic([...vc.match()], [...res])).toBe(true); expect(() => vc.add(meaninglessQuad)).toThrow("Cannot mutate this dataset"); expect(() => vc.delete(meaninglessQuad)).toThrow( - "Cannot mutate this dataset" + "Cannot mutate this dataset", ); expect(vc.has(meaninglessQuad)).toBe(false); expect(vc.has(issuerQuad)).toBe(true); expect(vc.size).toBe(13); expect( vc.match( - DataFactory.namedNode("https://example.org/ns/someCredentialInstance") - ).size + DataFactory.namedNode("https://example.org/ns/someCredentialInstance"), + ).size, ).toBe(6); }); @@ -839,7 +839,7 @@ describe("getVerifiableCredential", () => { for (const quad of store.match( null, DataFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), - DataFactory.namedNode("https://w3id.org/security#Ed25519Signature2018") + DataFactory.namedNode("https://w3id.org/security#Ed25519Signature2018"), )) { store.delete(quad); store.add( @@ -847,13 +847,13 @@ describe("getVerifiableCredential", () => { quad.subject, quad.predicate, DataFactory.namedNode("https://w3id.org/security#notARealSignature"), - quad.graph - ) + quad.graph, + ), ); } expect( - await getVerifiableCredentialFromStore(store, "https://some.vc") + await getVerifiableCredentialFromStore(store, "https://some.vc"), ).toMatchObject( Object.assign(mockDefaultCredential(), { size: 13, @@ -882,7 +882,7 @@ describe("getVerifiableCredential", () => { proofPurpose: "https://w3id.org/security#assertionMethod", type: "https://w3id.org/security#notARealSignature", }, - }) + }), ); }); @@ -892,7 +892,7 @@ describe("getVerifiableCredential", () => { for (const quad of store.match( null, DataFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), - DataFactory.namedNode("https://w3id.org/security#Ed25519Signature2018") + DataFactory.namedNode("https://w3id.org/security#Ed25519Signature2018"), )) { store.removeQuad(quad); store.add( @@ -900,15 +900,15 @@ describe("getVerifiableCredential", () => { quad.subject, quad.predicate, DataFactory.namedNode( - "https://www.w3.org/2018/credentials#VerifiableCredential" + "https://www.w3.org/2018/credentials#VerifiableCredential", ), - quad.graph - ) + quad.graph, + ), ); } expect( - await getVerifiableCredentialFromStore(store, "https://some.vc") + await getVerifiableCredentialFromStore(store, "https://some.vc"), ).toMatchObject( Object.assign(mockDefaultCredential(), { size: 13, @@ -937,7 +937,7 @@ describe("getVerifiableCredential", () => { proofPurpose: "sec:assertionMethod", type: "VerifiableCredential", }, - }) + }), ); }); @@ -948,23 +948,23 @@ describe("getVerifiableCredential", () => { null, DataFactory.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), DataFactory.namedNode( - "https://www.w3.org/2018/credentials#VerifiableCredential" - ) + "https://www.w3.org/2018/credentials#VerifiableCredential", + ), )) { store.add( DataFactory.quad( quad.subject, quad.predicate, DataFactory.namedNode( - "https://www.w3.org/2018/credentials#VerifiablePresentation" + "https://www.w3.org/2018/credentials#VerifiablePresentation", ), - quad.graph - ) + quad.graph, + ), ); } expect( - await getVerifiableCredentialFromStore(store, "https://some.vc") + await getVerifiableCredentialFromStore(store, "https://some.vc"), ).toMatchObject( Object.assign(mockDefaultCredential(), { size: 14, @@ -986,7 +986,7 @@ describe("getVerifiableCredential", () => { }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential", "VerifiablePresentation"], - }) + }), ); }); @@ -997,20 +997,20 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicateBnode"), - DataFactory.blankNode("b2") - ) + DataFactory.blankNode("b2"), + ), ); store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicate"), - DataFactory.namedNode("https://example.org/object") - ) + DataFactory.namedNode("https://example.org/object"), + ), ); expect( - await getVerifiableCredentialFromStore(store, "https://some.vc") + await getVerifiableCredentialFromStore(store, "https://some.vc"), ).toMatchObject( Object.assign(mockDefaultCredential(), { size: 15, @@ -1036,7 +1036,7 @@ describe("getVerifiableCredential", () => { }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], - }) + }), ); }); @@ -1047,28 +1047,28 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicateBnode"), - DataFactory.blankNode("b2") - ) + DataFactory.blankNode("b2"), + ), ); store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicate"), - DataFactory.namedNode("https://example.org/object") - ) + DataFactory.namedNode("https://example.org/object"), + ), ); store.add( DataFactory.quad( DataFactory.blankNode("b2"), DataFactory.namedNode("https://example.org/predicate"), - DataFactory.blankNode("b2") - ) + DataFactory.blankNode("b2"), + ), ); expect( - await getVerifiableCredentialFromStore(store, "https://some.vc") + await getVerifiableCredentialFromStore(store, "https://some.vc"), ).toMatchObject( Object.assign(mockDefaultCredential(), { size: 16, @@ -1099,7 +1099,7 @@ describe("getVerifiableCredential", () => { }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], - }) + }), ); }); @@ -1110,36 +1110,36 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicateBnode"), - DataFactory.blankNode("b2") - ) + DataFactory.blankNode("b2"), + ), ); store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicateBnode"), - DataFactory.blankNode("b3") - ) + DataFactory.blankNode("b3"), + ), ); store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicate"), - DataFactory.namedNode("https://example.org/object") - ) + DataFactory.namedNode("https://example.org/object"), + ), ); store.add( DataFactory.quad( DataFactory.blankNode("b2"), DataFactory.namedNode("https://example.org/predicate"), - DataFactory.blankNode("b2") - ) + DataFactory.blankNode("b2"), + ), ); expect( - await getVerifiableCredentialFromStore(store, "https://some.vc") + await getVerifiableCredentialFromStore(store, "https://some.vc"), ).toMatchObject( Object.assign(mockDefaultCredential(), { size: 17, @@ -1175,7 +1175,7 @@ describe("getVerifiableCredential", () => { }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], - }) + }), ); }); }); @@ -1183,7 +1183,10 @@ describe("getVerifiableCredential", () => { describe("getVerifiableCredentialFromResponse", () => { it("should error if the response has no content type", () => { return expect( - getVerifiableCredentialFromResponse(new Response(), "https://example.org") + getVerifiableCredentialFromResponse( + new Response(), + "https://example.org", + ), ).rejects.toThrow("Response does not have a Content-Type"); }); }); diff --git a/src/common/common.ts b/src/common/common.ts index e0b1a27a..136e207a 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -412,14 +412,14 @@ export async function getVerifiableCredentialApiConfiguration( function validateVcResponse(response: Response, vcUrl: string): Response { if (!response.ok) { throw new Error( - `Fetching the Verifiable Credential [${vcUrl}] failed: ${response.status} ${response.statusText}` + `Fetching the Verifiable Credential [${vcUrl}] failed: ${response.status} ${response.statusText}`, ); } const contentType = response.headers.get("Content-Type"); if (!contentType) { throw new Error( - `Fetching the Verifiable Credential [${vcUrl}] failed: Response does not have a Content-Type header; expected application/ld+json` + `Fetching the Verifiable Credential [${vcUrl}] failed: Response does not have a Content-Type header; expected application/ld+json`, ); } @@ -434,7 +434,7 @@ function validateVcResponse(response: Response, vcUrl: string): Response { !subtypes.includes("json") ) { throw new Error( - `Fetching the Verifiable Credential [${vcUrl}] failed: Response has an unsupported Content-Type [${contentType}]; expected application/ld+json` + `Fetching the Verifiable Credential [${vcUrl}] failed: Response has an unsupported Content-Type [${contentType}]; expected application/ld+json`, ); } @@ -446,7 +446,7 @@ async function responseToVcStore( vcUrl: UrlString, options?: Partial<{ fetch: typeof fetch; - }> + }>, ): Promise { try { return await jsonLdResponseToStore(validateVcResponse(response, vcUrl), { @@ -455,7 +455,7 @@ async function responseToVcStore( }); } catch (e) { throw new Error( - `Parsing the Verifiable Credential [${vcUrl}] as JSON-LD failed: ${e}` + `Parsing the Verifiable Credential [${vcUrl}] as JSON-LD failed: ${e}`, ); } } @@ -481,25 +481,25 @@ const PROOF_VALUE = `${SEC}proofValue`; */ export async function getVerifiableCredentialFromStore( vcStore: Store, - vcUrl: UrlString + vcUrl: UrlString, ): Promise { const vcContext = await getVcContext(); const vcs = vcStore.getSubjects( RDF_TYPE, VERIFIABLE_CREDENTIAL, - DF.defaultGraph() + DF.defaultGraph(), ); if (vcs.length !== 1) { throw new Error( - `Expected exactly one Verifiable Credential in [${vcUrl}], received: ${vcs.length}` + `Expected exactly one Verifiable Credential in [${vcUrl}], received: ${vcs.length}`, ); } const [vc] = vcs; if (vc.termType !== "NamedNode") { throw new Error( - `Expected the Verifiable Credential in [${vcUrl}] to be a Named Node, received: ${vc.termType}` + `Expected the Verifiable Credential in [${vcUrl}] to be a Named Node, received: ${vc.termType}`, ); } @@ -507,7 +507,7 @@ export async function getVerifiableCredentialFromStore( for (const t of vcStore.getObjects(vc, RDF_TYPE, DF.defaultGraph())) { if (t.termType !== "NamedNode") { throw new Error( - `Expected all VC types to be Named Nodes but received [${t.value}] of termType [${t.termType}]` + `Expected all VC types to be Named Nodes but received [${t.value}] of termType [${t.termType}]`, ); } @@ -519,13 +519,13 @@ export async function getVerifiableCredentialFromStore( function getSingleObject( fullProperty: string, subject?: Term, - graph: Term = DF.defaultGraph() + graph: Term = DF.defaultGraph(), ): Term { const objects = vcStore.getObjects(subject ?? vc, fullProperty, graph); if (objects.length !== 1) { throw new Error( - `Expected exactly one [${fullProperty}] for the Verifiable Credential ${vc.value}, received: ${objects.length}` + `Expected exactly one [${fullProperty}] for the Verifiable Credential ${vc.value}, received: ${objects.length}`, ); } @@ -537,13 +537,13 @@ export async function getVerifiableCredentialFromStore( subject?: Term, graph?: Term, termType = "NamedNode", - customContext = vcContext + customContext = vcContext, ) { const object = getSingleObject(fullProperty, subject, graph); if (object.termType !== termType) { throw new Error( - `Expected property [${fullProperty}] of the Verifiable Credential [${vc.value}] to be a ${termType}, received: ${object.termType}` + `Expected property [${fullProperty}] of the Verifiable Credential [${vc.value}] to be a ${termType}, received: ${object.termType}`, ); } @@ -556,18 +556,18 @@ export async function getVerifiableCredentialFromStore( function getSingleDateTime( fullProperty: string, subject?: Term, - graph?: Term + graph?: Term, ) { const object = getSingleObject(fullProperty, subject, graph); if (object.termType !== "Literal") { throw new Error( - `Expected issuanceDate to be a Literal, received: ${object.termType}` + `Expected issuanceDate to be a Literal, received: ${object.termType}`, ); } if (!object.datatype.equals(DF.namedNode(DATE_TIME))) { throw new Error( - `Expected issuanceDate to have dataType [${DATE_TIME}], received: [${object.datatype.value}]` + `Expected issuanceDate to have dataType [${DATE_TIME}], received: [${object.datatype.value}]`, ); } @@ -584,7 +584,7 @@ export async function getVerifiableCredentialFromStore( if (proofs.length !== 1) { throw new Error( - `Expected exactly one proof to live in the proofs graph, received ${proofs.length}` + `Expected exactly one proof to live in the proofs graph, received ${proofs.length}`, ); } @@ -609,7 +609,7 @@ export async function getVerifiableCredentialFromStore( ) { proofPurposeContext = await getVcContext( proposedContext, - proposedContext.proofPurpose["@context"] + proposedContext.proofPurpose["@context"], ); } else { proofPurposeContext = proofContext; @@ -622,7 +622,7 @@ export async function getVerifiableCredentialFromStore( for (const predicate of vcStore.getPredicates( subject, null, - DF.defaultGraph() + DF.defaultGraph(), )) { if (predicate.termType !== "NamedNode") { throw new Error("Predicate must be a namedNode"); @@ -635,7 +635,7 @@ export async function getVerifiableCredentialFromStore( // eslint-disable-next-line @typescript-eslint/no-use-before-define .map((obj) => writeObject(obj, writtenTerms)) .filter( - (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1 + (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1, ); if (objects.length === 1) { @@ -689,14 +689,14 @@ export async function getVerifiableCredentialFromStore( created: getSingleDateTime( "http://purl.org/dc/terms/created", proof, - proofGraph + proofGraph, ), proofPurpose: getSingleObjectOfTermType( PROOF_PURPOSE, proof, proofGraph, "NamedNode", - proofPurposeContext + proofPurposeContext, ), type: proofType, verificationMethod: getSingleObjectOfTermType( @@ -704,13 +704,13 @@ export async function getVerifiableCredentialFromStore( proof, proofGraph, "NamedNode", - proofContext + proofContext, ), proofValue: getSingleObjectOfTermType( PROOF_VALUE, proof, proofGraph, - "Literal" + "Literal", ), }, @@ -753,7 +753,7 @@ export async function getVerifiableCredentialFromResponse( vcUrl: UrlString, options?: Partial<{ fetch: typeof fetch; - }> + }>, ): Promise { const vcStore = await responseToVcStore(response, vcUrl, options); return getVerifiableCredentialFromStore(vcStore, vcUrl); @@ -772,7 +772,7 @@ export async function getVerifiableCredential( vcUrl: UrlString, options?: Partial<{ fetch: typeof fetch; - }> + }>, ): Promise { const authFetch = options?.fetch ?? uniFetch; const response = await authFetch(vcUrl); diff --git a/src/parser/jsonld.test.ts b/src/parser/jsonld.test.ts index 86e3c137..7a472a09 100644 --- a/src/parser/jsonld.test.ts +++ b/src/parser/jsonld.test.ts @@ -44,13 +44,13 @@ const fetcher: (typeof UniversalFetch)["fetch"] = async (url) => { }), { headers: new Headers([["content-type", "application/ld+json"]]), - } + }, ); }; jest.mock("@inrupt/universal-fetch", () => { const fetchModule = jest.requireActual( - "@inrupt/universal-fetch" + "@inrupt/universal-fetch", ) as typeof UniversalFetch; return { ...fetchModule, @@ -88,12 +88,12 @@ const result = [ DF.quad( DF.namedNode("https://some.example#credential"), DF.namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), - DF.namedNode("https://www.w3.org/2018/credentials#VerifiableCredential") + DF.namedNode("https://www.w3.org/2018/credentials#VerifiableCredential"), ), DF.quad( DF.namedNode("https://some.example#credential"), DF.namedNode("https://www.w3.org/2018/credentials#issuer"), - DF.namedNode("https://some.example") + DF.namedNode("https://some.example"), ), ]; @@ -101,7 +101,7 @@ describe("jsonLdResponseToStore", () => { it("converting fetch response to a store", async () => { const response = new Response(JSON.stringify(data)); expect( - isomorphic([...(await jsonLdResponseToStore(response))], result) + isomorphic([...(await jsonLdResponseToStore(response))], result), ).toBe(true); }); @@ -114,13 +114,13 @@ describe("jsonLdResponseToStore", () => { it("rejects on empty fetch response", async () => { await expect(jsonLdResponseToStore(new Response())).rejects.toThrow( - "Empty response body. Expected JSON-LD." + "Empty response body. Expected JSON-LD.", ); }); it("rejects on invalid JSON-LD", async () => { await expect(jsonLdResponseToStore(new Response("{"))).rejects.toThrow( - "Error parsing JSON-LD: [Error: Unclosed document]." + "Error parsing JSON-LD: [Error: Unclosed document].", ); }); @@ -133,10 +133,10 @@ describe("jsonLdResponseToStore", () => { DF.quad( DF.namedNode("https://some.example#credential"), DF.namedNode("http://xmlns.com/foaf/0.1/name"), - DF.literal("Inrupt") + DF.literal("Inrupt"), ), - ] - ) + ], + ), ).toBe(true); }); }); @@ -158,20 +158,20 @@ describe("getVcContext", () => { expect( context.compactIri( "https://www.w3.org/2018/credentials#VerifiableCredential", - true - ) + true, + ), ).toBe("VerifiableCredential"); expect(context.expandTerm("VerifiableCredential", true)).toBe( - "https://www.w3.org/2018/credentials#VerifiableCredential" + "https://www.w3.org/2018/credentials#VerifiableCredential", ); }); it("should be able to compact and expand IRIs from the Inrupt context", () => { expect(context.compactIri("https://w3id.org/GConsent#Consent", true)).toBe( - "Consent" + "Consent", ); expect(context.expandTerm("Consent", true)).toBe( - "https://w3id.org/GConsent#Consent" + "https://w3id.org/GConsent#Consent", ); }); @@ -179,8 +179,8 @@ describe("getVcContext", () => { expect( context.compactIri( "https://example.org/credentials#VerifiableCredential", - true - ) + true, + ), ).toBe("https://example.org/credentials#VerifiableCredential"); expect(context.expandTerm("VC", true)).toBe("VC"); }); diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index c9744563..9f197399 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -71,7 +71,7 @@ export class CachedJsonLdParser extends JsonLdParser { constructor(options?: Options) { super({ documentLoader: new CachedFetchDocumentLoader( - options?.fetch ?? defaultFetch + options?.fetch ?? defaultFetch, ), baseIRI: options?.baseIRI, }); @@ -105,7 +105,7 @@ export async function jsonLdStringToStore(data: string, options?: Options) { */ export async function jsonLdResponseToStore( response: Response, - options?: Options + options?: Options, ): Promise { if (response.body === null) throw new Error("Empty response body. Expected JSON-LD."); From 5967c0bd5659022c26cc6359ce61c2f6d03474a5 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Mon, 21 Aug 2023 19:20:41 +1000 Subject: [PATCH 18/35] chore: remove suggestion to check for ld media type --- src/common/common.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 136e207a..3d2d1842 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -429,8 +429,6 @@ function validateVcResponse(response: Response, vcUrl: string): Response { if ( mediaType !== "application" || - // TODO: See if the response is expected to include the ld - // || !subtypes.includes('ld') !subtypes.includes("json") ) { throw new Error( From 447288210773e0be97235612a7e010b6c5a904a8 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Mon, 21 Aug 2023 19:21:19 +1000 Subject: [PATCH 19/35] chore: fix lint error --- src/common/common.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 3d2d1842..14e19297 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -427,10 +427,7 @@ function validateVcResponse(response: Response, vcUrl: string): Response { const [mediaType, subtypesString] = parsedContentType.type.split("/"); const subtypes = subtypesString.split("+"); - if ( - mediaType !== "application" || - !subtypes.includes("json") - ) { + if (mediaType !== "application" || !subtypes.includes("json")) { throw new Error( `Fetching the Verifiable Credential [${vcUrl}] failed: Response has an unsupported Content-Type [${contentType}]; expected application/ld+json`, ); From 860faf3e3286fa32c99d9f64a9777ff044494a5f Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Thu, 31 Aug 2023 11:53:18 +1000 Subject: [PATCH 20/35] chore: export getVerifiableCredentialFromResponse --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index e98d64f9..e5ba2ed3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,7 @@ export { default as issueVerifiableCredential } from "./issue/issue"; export type { Iri, JsonLd, VerifiableCredential } from "./common/common"; +export { getVerifiableCredentialFromResponse } from "./common/common"; export { isVerifiableCredential, isVerifiablePresentation, From 23aca8f28ea389412d8912f6ce4d4fd68f341eff Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:30:18 +0900 Subject: [PATCH 21/35] chore: fix export test --- src/index.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/index.test.ts b/src/index.test.ts index d7732fa0..cce31320 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -26,6 +26,7 @@ import { isVerifiablePresentation, getVerifiableCredential, getVerifiableCredentialApiConfiguration, + getVerifiableCredentialFromResponse, } from "./common/common"; import getVerifiableCredentialAllFromShape from "./lookup/derive"; import revokeVerifiableCredential from "./revoke/revoke"; @@ -36,6 +37,7 @@ describe("exports", () => { it("includes all of the expected functions", () => { expect(Object.keys(packageExports)).toEqual([ "issueVerifiableCredential", + "getVerifiableCredentialFromResponse", "isVerifiableCredential", "isVerifiablePresentation", "getVerifiableCredential", @@ -49,6 +51,9 @@ describe("exports", () => { expect(packageExports.issueVerifiableCredential).toBe( issueVerifiableCredential, ); + expect(packageExports.getVerifiableCredentialFromResponse).toBe( + getVerifiableCredentialFromResponse, + ); expect(packageExports.isVerifiableCredential).toBe(isVerifiableCredential); expect(packageExports.isVerifiablePresentation).toBe( isVerifiablePresentation, From 11f1674d04d3f9ae23fef6e89d42a20f205cfa2d Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Tue, 19 Sep 2023 20:40:36 +0900 Subject: [PATCH 22/35] fix: add parser dependencies --- package-lock.json | 8 +++++--- package.json | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 59930347..ebc102b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,8 @@ "@inrupt/universal-fetch": "^1.0.1", "content-type": "^1.0.5", "event-emitter-promisify": "^1.1.0", + "jsonld-context-parser": "^2.3.0", + "jsonld-streaming-parser": "^3.2.1", "jsonld-streaming-serializer": "^2.1.0", "n3": "^1.17.0" }, @@ -6612,9 +6614,9 @@ "integrity": "sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==" }, "node_modules/jsonld-streaming-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonld-streaming-parser/-/jsonld-streaming-parser-3.2.0.tgz", - "integrity": "sha512-lJR1SCT364PGpFrOQaY+ZQ7qDWqqiT3IMK+AvZ83fo0LvltFn8/UyXvIFc3RO7YcaEjLahAF0otCi8vOq21NtQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonld-streaming-parser/-/jsonld-streaming-parser-3.2.1.tgz", + "integrity": "sha512-MZCUrQe3pBO2pk2i3BpyW9Yn2oZoe2RCRpHZAJa88S6tRyxbe7XcjWfTKAZv35obDJDIREgot4723VhbClJELw==", "dependencies": { "@bergos/jsonparse": "^1.4.0", "@rdfjs/types": "*", diff --git a/package.json b/package.json index 13089974..07af6265 100644 --- a/package.json +++ b/package.json @@ -72,8 +72,8 @@ "eslint": "^8.18.0", "jest": "^29.3.0", "jest-environment-jsdom": "^29.3.0", - "rdf-isomorphic": "^1.3.1", "prettier": "^3.0.2", + "rdf-isomorphic": "^1.3.1", "rollup": "^3.1.0", "rollup-plugin-typescript2": "^0.35.0", "ts-jest": "^29.0.3", @@ -90,6 +90,8 @@ "@inrupt/universal-fetch": "^1.0.1", "content-type": "^1.0.5", "event-emitter-promisify": "^1.1.0", + "jsonld-context-parser": "^2.3.0", + "jsonld-streaming-parser": "^3.2.1", "jsonld-streaming-serializer": "^2.1.0", "n3": "^1.17.0" }, From 7d29d9611ac45e909589de9cb785dbaef4502a93 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:41:55 +0900 Subject: [PATCH 23/35] WIP: properly shorten URIs and only put them in id when necessary --- src/common/common.test.ts | 4 +- src/common/common.ts | 129 +++++++++++++++++++++++++++++++++++--- src/parser/jsonld.ts | 2 +- 3 files changed, 124 insertions(+), 11 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 34be1d99..4d1ef819 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -879,8 +879,8 @@ describe("getVerifiableCredential", () => { ...mockDefaultCredential().proof, // Proof purpose has full URI as compacting this relies on the // context of the "type" - proofPurpose: "https://w3id.org/security#assertionMethod", - type: "https://w3id.org/security#notARealSignature", + proofPurpose: "sec:assertionMethod", + type: "sec:notARealSignature", }, }), ); diff --git a/src/common/common.ts b/src/common/common.ts index 14e19297..50e8d821 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -33,7 +33,7 @@ import { import { fetch as uniFetch } from "@inrupt/universal-fetch"; import { Util } from "jsonld-streaming-serializer"; import type { DatasetCore } from "@rdfjs/types"; -import type { Store, Term } from "n3"; +import type { BlankNode, Store, Term } from "n3"; import { DataFactory as DF } from "n3"; import contentTypeParser from "content-type"; import VcContext from "../parser/contexts/vc"; @@ -460,6 +460,8 @@ const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; const XSD = "http://www.w3.org/2001/XMLSchema#"; const SEC = "https://w3id.org/security#"; const CRED = "https://www.w3.org/2018/credentials#"; +const GCONSENT = "https://w3id.org/GConsent#"; +const ACL = "http://www.w3.org/ns/auth/acl#"; const RDF_TYPE = `${RDF}type`; const VERIFIABLE_CREDENTIAL = `${VC}VerifiableCredential`; const DATE_TIME = `${XSD}dateTime`; @@ -471,6 +473,18 @@ const PROOF_PURPOSE = `${SEC}proofPurpose`; const VERIFICATION_METHOD = `${SEC}verificationMethod`; const PROOF_VALUE = `${SEC}proofValue`; +const HAS_CONSENT = `${GCONSENT}hasConsent`; +const IS_PROVIDED_TO = `${GCONSENT}isProvidedTo`; +const FOR_PERSONAL_DATA = `${GCONSENT}forPersonalData`; +const HAS_STATUS = `${GCONSENT}hasStatus`; +const FOR_DATA_SUBJECT = `${GCONSENT}isConsentForDataSubject`; +const MODE = `${ACL}mode`; +const PROVIDED_CONSENT = `${ACL}providedConsent`; + +const inherit = "urn:uuid:71ab2f68-a68b-4452-b968-dd23e0570227"; + +// FIXME: Just add a general check for `@type` + /** * @hidden */ @@ -478,7 +492,7 @@ export async function getVerifiableCredentialFromStore( vcStore: Store, vcUrl: UrlString, ): Promise { - const vcContext = await getVcContext(); + let vcContext = await getVcContext(); const vcs = vcStore.getSubjects( RDF_TYPE, @@ -499,6 +513,8 @@ export async function getVerifiableCredentialFromStore( } const type: string[] = []; + const typeContexts: any[] = []; + for (const t of vcStore.getObjects(vc, RDF_TYPE, DF.defaultGraph())) { if (t.termType !== "NamedNode") { throw new Error( @@ -506,11 +522,20 @@ export async function getVerifiableCredentialFromStore( ); } + // Note that compact IRI by definition is of the form prefx:suffix so that might be the reason + // that some of the very short forms of the IRIs are not showing up here const compact = vcContext.compactIri(t.value, true); + if (compact in VcContext['@context']) { + typeContexts.push((VcContext as any)['@context'][compact]['@context']) + } + if (/^[a-z]+$/i.test(compact)) type.push(compact); } + // This allows any context specific to the type of the things that we are re-framing to be applied + vcContext = await getVcContext(...typeContexts); + function getSingleObject( fullProperty: string, subject?: Term, @@ -531,7 +556,7 @@ export async function getVerifiableCredentialFromStore( fullProperty: string, subject?: Term, graph?: Term, - termType = "NamedNode", + termType: Term['termType'] = "NamedNode", customContext = vcContext, ) { const object = getSingleObject(fullProperty, subject, graph); @@ -597,7 +622,7 @@ export async function getVerifiableCredentialFromStore( let proofPurposeContext = vcContext; if (typeof proposedContext === "object") { - proofContext = await getVcContext(proposedContext); + proofContext = await getVcContext(proposedContext, ...typeContexts); if ( "proofPurpose" in proposedContext && typeof proposedContext.proofPurpose["@context"] === "object" @@ -605,6 +630,7 @@ export async function getVerifiableCredentialFromStore( proofPurposeContext = await getVcContext( proposedContext, proposedContext.proofPurpose["@context"], + ...typeContexts ); } else { proofPurposeContext = proofContext; @@ -628,7 +654,7 @@ export async function getVerifiableCredentialFromStore( .getObjects(subject, predicate, DF.defaultGraph()) // writeObject and getProperties depend on each other circularly // eslint-disable-next-line @typescript-eslint/no-use-before-define - .map((obj) => writeObject(obj, writtenTerms)) + .map((obj) => writeObject(obj, writtenTerms, predicate.value)) .filter( (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1, ); @@ -646,7 +672,7 @@ export async function getVerifiableCredentialFromStore( let i = 0; const data: Record = {}; - function writeObject(object: Term, writtenTerms: string[]) { + function writeObject(object: Term, writtenTerms: string[], predicate: string, customContext = vcContext) { switch (object.termType) { case "BlankNode": { const obj = writtenTerms.includes(object.value) @@ -660,14 +686,27 @@ export async function getVerifiableCredentialFromStore( // eslint-disable-next-line no-fallthrough case "NamedNode": case "Literal": - return Util.termToValue(object, vcContext); + const compact = customContext.compactIri(predicate, true); + const termContext = customContext.getContextRaw()[compact]; + const term = Util.termToValue(object, customContext, { + compactIds: termContext && ('@type' in termContext), + vocab: true, + useNativeTypes: true + }); + + // Special case + if (term['@value'] === true || term['@value'] === false) { + return term['@value'] + } + return term; default: throw new Error(`Unexpected term type: ${object.termType}`); } } const credentialSubjectTerm = getSingleObjectOfTermType(CREDENTIAL_SUBJECT); - return { + + const res: VerifiableCredential & DatasetCore = { "@context": context, id: vc.value, // It is possible to have multiple claims in a credential subject @@ -732,6 +771,80 @@ export async function getVerifiableCredentialFromStore( return vcStore.size; }, }; + + // let prop: { key: 'hasConsent' | 'providedConsent'; node: BlankNode } | undefined = undefined; + + // for (const [key, pred] of [['hasConsent', HAS_CONSENT], ['providedConsent', PROVIDED_CONSENT]] as const) { + // try { + // prop = { key, node: DF.blankNode( + // getSingleObjectOfTermType(pred, DF.namedNode(credentialSubjectTerm), DF.defaultGraph(), 'BlankNode') + // ) } + // } catch (e) { + // // do nothing + // } + // } + + // if (prop) { + // try { + // function getNamedNodeObjects(store: Store, ...args: Parameters) { + // return store.getObjects(...args).map(term => { + // if (term.termType !== 'NamedNode') { + // throw new Error(`Expected [${term.value}] to have termType NamedNode. Got [${term.termType}].`) + // } + // return term.value + // }) + // } + + // const hasConsent: Record = { + // forPersonalData: getNamedNodeObjects(vcStore, prop.node, FOR_PERSONAL_DATA, DF.defaultGraph()), + // hasStatus: getSingleObjectOfTermType(HAS_STATUS, prop.node, DF.defaultGraph(), 'NamedNode'), + // isProvidedTo: getSingleObjectOfTermType(IS_PROVIDED_TO, prop.node, DF.defaultGraph(), 'NamedNode'), + // mode: getNamedNodeObjects(vcStore, prop.node, MODE, DF.defaultGraph()), + // isConsentForDataSubject: getSingleObjectOfTermType(FOR_DATA_SUBJECT, prop.node, DF.defaultGraph(), 'NamedNode'), + // } + // const inheritValues = vcStore.getObjects(prop.node, DF.namedNode(inherit), DF.defaultGraph()); + + // for (const elem of inheritValues) { + // if (elem.termType !== "Literal") { + // throw new Error(`Expected inherit value to be a Literal. Instead recieved [${elem.value}] of type [${elem.termType}]`); + // } + // if (!elem.datatype.equals(DF.namedNode('http://www.w3.org/2001/XMLSchema#boolean'))) { + // throw new Error(`Expected inherit value to be a boolean. Instead recieved [${elem.value}] with datatype [${elem.datatypeString}]`); + // } + // } + + // if (inheritValues.length > 1) { + // throw new Error(`Expected at most one value for inherit. Received ${inheritValues.length}`); + // } + + // if (inheritValues.length === 1) { + // hasConsent.inherit = inheritValues[0].value + // } + + // res.credentialSubject[prop.key] = hasConsent; + // } catch (e) { + // console.log(`Error overrriding hasConsent [${e}]`) + // // Do nothingIS_PROVIDED_TO + // } + // } + + +// Do hasConsent explicitly so we can frame things in the expected + // manner (in particular making sure single results such as "http://www.w3.org/ns/auth/acl#Read" are still in a list) + // for modes etc. + // NOTE: This *is* specific to access grants, and makes the following normalization code in the access grants library redundant: + // - https://github.com/inrupt/solid-client-access-grants-js/blob/ce63dc6591a286c1847ac9b5537af7c953437d8a/src/gConsent/request/issueAccessRequest.ts#L44 + // - https://github.com/inrupt/solid-client-access-grants-js/blob/ce63dc6591a286c1847ac9b5537af7c953437d8a/src/gConsent/manage/approveAccessRequest.ts#L61 + // hasConsent: { + // forPersonalData: ["https://some.resource"], + // hasStatus: getSingleObjectOfTermType, + // mode: ["http://www.w3.org/ns/auth/acl#Read"], + // isProvidedTo: getSingleObjectOfTermType(HAS_CONSENT, DF.namedNode(credentialSubjectTerm), DF.defaultGraph(), 'BlankNode'), + // inherit: options?.inherit ?? true, + // isConsentForDataSubject: + // }, + + return res; } /** diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index 9f197399..146df4ed 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -56,7 +56,7 @@ export function getVcContext( const myParser = new ContextParser({ documentLoader: new CachedFetchDocumentLoader(), }); - return myParser.parse([...Object.values(CONTEXTS), ...contexts]); + return myParser.parse([...Object.values(CONTEXTS).map(x => x['@context']), ...contexts]); } interface Options { From 4ceca8fc630383fba38b5c55e7d71262b81b7532 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:46:10 +0900 Subject: [PATCH 24/35] chore: remove custom hasContext code --- src/common/common.ts | 132 ++++++++++--------------------------------- src/parser/jsonld.ts | 5 +- 2 files changed, 34 insertions(+), 103 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 50e8d821..711e0a6a 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -26,18 +26,18 @@ import type { UrlString } from "@inrupt/solid-client"; import { getIri, + getJsonLdParser, getSolidDataset, getThingAll, - getJsonLdParser, } from "@inrupt/solid-client"; import { fetch as uniFetch } from "@inrupt/universal-fetch"; -import { Util } from "jsonld-streaming-serializer"; import type { DatasetCore } from "@rdfjs/types"; -import type { BlankNode, Store, Term } from "n3"; -import { DataFactory as DF } from "n3"; import contentTypeParser from "content-type"; -import VcContext from "../parser/contexts/vc"; +import { Util } from "jsonld-streaming-serializer"; +import type { Store, Term } from "n3"; +import { DataFactory as DF } from "n3"; import { context } from "../parser/contexts"; +import VcContext from "../parser/contexts/vc"; import { getVcContext, jsonLdResponseToStore } from "../parser/jsonld"; export type Iri = string; @@ -460,8 +460,6 @@ const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; const XSD = "http://www.w3.org/2001/XMLSchema#"; const SEC = "https://w3id.org/security#"; const CRED = "https://www.w3.org/2018/credentials#"; -const GCONSENT = "https://w3id.org/GConsent#"; -const ACL = "http://www.w3.org/ns/auth/acl#"; const RDF_TYPE = `${RDF}type`; const VERIFIABLE_CREDENTIAL = `${VC}VerifiableCredential`; const DATE_TIME = `${XSD}dateTime`; @@ -473,18 +471,6 @@ const PROOF_PURPOSE = `${SEC}proofPurpose`; const VERIFICATION_METHOD = `${SEC}verificationMethod`; const PROOF_VALUE = `${SEC}proofValue`; -const HAS_CONSENT = `${GCONSENT}hasConsent`; -const IS_PROVIDED_TO = `${GCONSENT}isProvidedTo`; -const FOR_PERSONAL_DATA = `${GCONSENT}forPersonalData`; -const HAS_STATUS = `${GCONSENT}hasStatus`; -const FOR_DATA_SUBJECT = `${GCONSENT}isConsentForDataSubject`; -const MODE = `${ACL}mode`; -const PROVIDED_CONSENT = `${ACL}providedConsent`; - -const inherit = "urn:uuid:71ab2f68-a68b-4452-b968-dd23e0570227"; - -// FIXME: Just add a general check for `@type` - /** * @hidden */ @@ -513,6 +499,7 @@ export async function getVerifiableCredentialFromStore( } const type: string[] = []; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const typeContexts: any[] = []; for (const t of vcStore.getObjects(vc, RDF_TYPE, DF.defaultGraph())) { @@ -526,8 +513,9 @@ export async function getVerifiableCredentialFromStore( // that some of the very short forms of the IRIs are not showing up here const compact = vcContext.compactIri(t.value, true); - if (compact in VcContext['@context']) { - typeContexts.push((VcContext as any)['@context'][compact]['@context']) + if (compact in VcContext["@context"]) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + typeContexts.push((VcContext as any)["@context"][compact]["@context"]); } if (/^[a-z]+$/i.test(compact)) type.push(compact); @@ -556,7 +544,7 @@ export async function getVerifiableCredentialFromStore( fullProperty: string, subject?: Term, graph?: Term, - termType: Term['termType'] = "NamedNode", + termType: Term["termType"] = "NamedNode", customContext = vcContext, ) { const object = getSingleObject(fullProperty, subject, graph); @@ -630,7 +618,7 @@ export async function getVerifiableCredentialFromStore( proofPurposeContext = await getVcContext( proposedContext, proposedContext.proofPurpose["@context"], - ...typeContexts + ...typeContexts, ); } else { proofPurposeContext = proofContext; @@ -672,7 +660,12 @@ export async function getVerifiableCredentialFromStore( let i = 0; const data: Record = {}; - function writeObject(object: Term, writtenTerms: string[], predicate: string, customContext = vcContext) { + function writeObject( + object: Term, + writtenTerms: string[], + predicate: string, + customContext = vcContext, + ) { switch (object.termType) { case "BlankNode": { const obj = writtenTerms.includes(object.value) @@ -685,20 +678,27 @@ export async function getVerifiableCredentialFromStore( } // eslint-disable-next-line no-fallthrough case "NamedNode": - case "Literal": + case "Literal": { const compact = customContext.compactIri(predicate, true); const termContext = customContext.getContextRaw()[compact]; const term = Util.termToValue(object, customContext, { - compactIds: termContext && ('@type' in termContext), + // If an `@type` is defined in the context, then the + // parser can determine that it is an IRI immediately + // and so we don't need to wrap it in an object with an + // `@id` entry. + compactIds: termContext && "@type" in termContext, vocab: true, - useNativeTypes: true + useNativeTypes: true, }); - // Special case - if (term['@value'] === true || term['@value'] === false) { - return term['@value'] + // Special case: Booleans (any any other native literals for + // that matter) don't need to be wrapped in an object with an + // `@value` key. + if (term["@value"] === true || term["@value"] === false) { + return term["@value"]; } return term; + } default: throw new Error(`Unexpected term type: ${object.termType}`); } @@ -772,78 +772,6 @@ export async function getVerifiableCredentialFromStore( }, }; - // let prop: { key: 'hasConsent' | 'providedConsent'; node: BlankNode } | undefined = undefined; - - // for (const [key, pred] of [['hasConsent', HAS_CONSENT], ['providedConsent', PROVIDED_CONSENT]] as const) { - // try { - // prop = { key, node: DF.blankNode( - // getSingleObjectOfTermType(pred, DF.namedNode(credentialSubjectTerm), DF.defaultGraph(), 'BlankNode') - // ) } - // } catch (e) { - // // do nothing - // } - // } - - // if (prop) { - // try { - // function getNamedNodeObjects(store: Store, ...args: Parameters) { - // return store.getObjects(...args).map(term => { - // if (term.termType !== 'NamedNode') { - // throw new Error(`Expected [${term.value}] to have termType NamedNode. Got [${term.termType}].`) - // } - // return term.value - // }) - // } - - // const hasConsent: Record = { - // forPersonalData: getNamedNodeObjects(vcStore, prop.node, FOR_PERSONAL_DATA, DF.defaultGraph()), - // hasStatus: getSingleObjectOfTermType(HAS_STATUS, prop.node, DF.defaultGraph(), 'NamedNode'), - // isProvidedTo: getSingleObjectOfTermType(IS_PROVIDED_TO, prop.node, DF.defaultGraph(), 'NamedNode'), - // mode: getNamedNodeObjects(vcStore, prop.node, MODE, DF.defaultGraph()), - // isConsentForDataSubject: getSingleObjectOfTermType(FOR_DATA_SUBJECT, prop.node, DF.defaultGraph(), 'NamedNode'), - // } - // const inheritValues = vcStore.getObjects(prop.node, DF.namedNode(inherit), DF.defaultGraph()); - - // for (const elem of inheritValues) { - // if (elem.termType !== "Literal") { - // throw new Error(`Expected inherit value to be a Literal. Instead recieved [${elem.value}] of type [${elem.termType}]`); - // } - // if (!elem.datatype.equals(DF.namedNode('http://www.w3.org/2001/XMLSchema#boolean'))) { - // throw new Error(`Expected inherit value to be a boolean. Instead recieved [${elem.value}] with datatype [${elem.datatypeString}]`); - // } - // } - - // if (inheritValues.length > 1) { - // throw new Error(`Expected at most one value for inherit. Received ${inheritValues.length}`); - // } - - // if (inheritValues.length === 1) { - // hasConsent.inherit = inheritValues[0].value - // } - - // res.credentialSubject[prop.key] = hasConsent; - // } catch (e) { - // console.log(`Error overrriding hasConsent [${e}]`) - // // Do nothingIS_PROVIDED_TO - // } - // } - - -// Do hasConsent explicitly so we can frame things in the expected - // manner (in particular making sure single results such as "http://www.w3.org/ns/auth/acl#Read" are still in a list) - // for modes etc. - // NOTE: This *is* specific to access grants, and makes the following normalization code in the access grants library redundant: - // - https://github.com/inrupt/solid-client-access-grants-js/blob/ce63dc6591a286c1847ac9b5537af7c953437d8a/src/gConsent/request/issueAccessRequest.ts#L44 - // - https://github.com/inrupt/solid-client-access-grants-js/blob/ce63dc6591a286c1847ac9b5537af7c953437d8a/src/gConsent/manage/approveAccessRequest.ts#L61 - // hasConsent: { - // forPersonalData: ["https://some.resource"], - // hasStatus: getSingleObjectOfTermType, - // mode: ["http://www.w3.org/ns/auth/acl#Read"], - // isProvidedTo: getSingleObjectOfTermType(HAS_CONSENT, DF.namedNode(credentialSubjectTerm), DF.defaultGraph(), 'BlankNode'), - // inherit: options?.inherit ?? true, - // isConsentForDataSubject: - // }, - return res; } diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index 146df4ed..708dff5d 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -56,7 +56,10 @@ export function getVcContext( const myParser = new ContextParser({ documentLoader: new CachedFetchDocumentLoader(), }); - return myParser.parse([...Object.values(CONTEXTS).map(x => x['@context']), ...contexts]); + return myParser.parse([ + ...Object.values(CONTEXTS).map((x) => x["@context"]), + ...contexts, + ]); } interface Options { From baaef5f223cc9a7fb8b9805090f927eddf08a32e Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Tue, 26 Sep 2023 18:41:33 +0900 Subject: [PATCH 25/35] feat: support custom contexts in the parser --- src/common/common.ts | 15 +++++---------- src/lookup/query.ts | 1 + src/parser/jsonld.ts | 36 ++++++++++++++++++++++++++++-------- src/verify/verify.ts | 2 ++ 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 711e0a6a..2dee8042 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -38,6 +38,7 @@ import type { Store, Term } from "n3"; import { DataFactory as DF } from "n3"; import { context } from "../parser/contexts"; import VcContext from "../parser/contexts/vc"; +import type { ParseOptions } from "../parser/jsonld"; import { getVcContext, jsonLdResponseToStore } from "../parser/jsonld"; export type Iri = string; @@ -439,13 +440,11 @@ function validateVcResponse(response: Response, vcUrl: string): Response { async function responseToVcStore( response: Response, vcUrl: UrlString, - options?: Partial<{ - fetch: typeof fetch; - }>, + options?: ParseOptions, ): Promise { try { return await jsonLdResponseToStore(validateVcResponse(response, vcUrl), { - fetch: options?.fetch, + ...options, baseIRI: vcUrl, }); } catch (e) { @@ -787,9 +786,7 @@ export async function getVerifiableCredentialFromStore( export async function getVerifiableCredentialFromResponse( response: Response, vcUrl: UrlString, - options?: Partial<{ - fetch: typeof fetch; - }>, + options?: ParseOptions, ): Promise { const vcStore = await responseToVcStore(response, vcUrl, options); return getVerifiableCredentialFromStore(vcStore, vcUrl); @@ -806,9 +803,7 @@ export async function getVerifiableCredentialFromResponse( */ export async function getVerifiableCredential( vcUrl: UrlString, - options?: Partial<{ - fetch: typeof fetch; - }>, + options?: ParseOptions, ): Promise { const authFetch = options?.fetch ?? uniFetch; const response = await authFetch(vcUrl); diff --git a/src/lookup/query.ts b/src/lookup/query.ts index 7d225be1..0d7ace55 100644 --- a/src/lookup/query.ts +++ b/src/lookup/query.ts @@ -119,6 +119,7 @@ export async function query( let data; try { + // FIXME: Perform parsing here data = normalizeVp(await response.json()); } catch (e) { throw new Error( diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index 708dff5d..746d36e2 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -36,11 +36,24 @@ import type { JsonLd } from "../common/common"; * A JSON-LD document loader with the standard context for VCs pre-loaded */ class CachedFetchDocumentLoader extends FetchDocumentLoader { + private contexts: Record; + + constructor( + contexts?: Record, + private readonly allowContextFetching = true, + ...args: ConstructorParameters + ) { + super(...args); + this.contexts = contexts ? { ...contexts, ...CONTEXTS } : CONTEXTS; + } + public async load(url: string): Promise { - if (Object.keys(CONTEXTS).includes(url)) { - return CONTEXTS[url as keyof typeof CONTEXTS]; + if (Object.keys(this.contexts).includes(url)) { + return this.contexts[url as keyof typeof CONTEXTS]; + } + if (!this.allowContextFetching) { + throw new Error(`Unexpected context requested [${url}]`); } - // FIXME: See if we want to error on other contexts return super.load(url); } } @@ -62,18 +75,22 @@ export function getVcContext( ]); } -interface Options { +export interface ParseOptions { fetch?: typeof globalThis.fetch; baseIRI?: string; + contexts?: Record; + allowContextFetching?: boolean; } /** * Our internal JsonLd Parser with a cached VC context */ export class CachedJsonLdParser extends JsonLdParser { - constructor(options?: Options) { + constructor(options?: ParseOptions) { super({ documentLoader: new CachedFetchDocumentLoader( + options?.contexts, + options?.allowContextFetching, options?.fetch ?? defaultFetch, ), baseIRI: options?.baseIRI, @@ -87,7 +104,10 @@ export class CachedJsonLdParser extends JsonLdParser { * @param options An optional fetch function for dereferencing remote contexts * @returns A store containing the Quads in the JSON-LD response */ -export async function jsonLdStringToStore(data: string, options?: Options) { +export async function jsonLdStringToStore( + data: string, + options?: ParseOptions, +) { try { const parser = new CachedJsonLdParser(options); const store = new Store(); @@ -108,7 +128,7 @@ export async function jsonLdStringToStore(data: string, options?: Options) { */ export async function jsonLdResponseToStore( response: Response, - options?: Options, + options?: ParseOptions, ): Promise { if (response.body === null) throw new Error("Empty response body. Expected JSON-LD."); @@ -144,6 +164,6 @@ export async function jsonLdResponseToStore( * @param options An optional fetch function for dereferencing remote contexts * @returns A store containing the Quads in the JSON-LD response */ -export function jsonLdToStore(data: JsonLd, options?: Options) { +export function jsonLdToStore(data: JsonLd, options?: ParseOptions) { return jsonLdStringToStore(JSON.stringify(data), options); } diff --git a/src/verify/verify.ts b/src/verify/verify.ts index 57b87f71..1d3e012e 100644 --- a/src/verify/verify.ts +++ b/src/verify/verify.ts @@ -135,6 +135,7 @@ export async function isValidVc( } try { + // FIXME: Perform parsing here return await response.json(); } catch (e) { throw new Error( @@ -217,6 +218,7 @@ export async function isValidVerifiablePresentation( } try { + // FIXME: Perform parsing here return await response.json(); } catch (e) { throw new Error( From df52507ccb61072620005e854dbccd338d0c25ef Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Wed, 18 Oct 2023 19:39:44 +0100 Subject: [PATCH 26/35] chore: re-enable skipped test --- package-lock.json | 8 ++++---- package.json | 2 +- src/parser/jsonld.test.ts | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index d8734ec1..1f9d387b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@inrupt/universal-fetch": "^1.0.1", "content-type": "^1.0.5", "event-emitter-promisify": "^1.1.0", - "jsonld-context-parser": "^2.3.0", + "jsonld-context-parser": "^2.3.3", "jsonld-streaming-parser": "^3.2.1", "jsonld-streaming-serializer": "^2.1.0", "n3": "^1.17.0" @@ -6587,9 +6587,9 @@ } }, "node_modules/jsonld-context-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/jsonld-context-parser/-/jsonld-context-parser-2.3.0.tgz", - "integrity": "sha512-c6w2GE57O26eWFjcPX6k6G86ootsIfpuVwhZKjCll0bVoDGBxr1P4OuU+yvgfnh1GJhAGErolfC7W1BklLjWMg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/jsonld-context-parser/-/jsonld-context-parser-2.3.3.tgz", + "integrity": "sha512-H+REInOx7XI2ciF8wJV31D20Bh+ofBmEjN2Tkds51vypqDJIiD341E5g+hYyrEInIKRnbW58TN/Ehz+ACT0l0w==", "dependencies": { "@types/http-link-header": "^1.0.1", "@types/node": "^18.0.0", diff --git a/package.json b/package.json index ccccc4ee..7335ef1a 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "@inrupt/universal-fetch": "^1.0.1", "content-type": "^1.0.5", "event-emitter-promisify": "^1.1.0", - "jsonld-context-parser": "^2.3.0", + "jsonld-context-parser": "^2.3.3", "jsonld-streaming-parser": "^3.2.1", "jsonld-streaming-serializer": "^2.1.0", "n3": "^1.17.0" diff --git a/src/parser/jsonld.test.ts b/src/parser/jsonld.test.ts index 7a472a09..870ef225 100644 --- a/src/parser/jsonld.test.ts +++ b/src/parser/jsonld.test.ts @@ -105,8 +105,7 @@ describe("jsonLdResponseToStore", () => { ).toBe(true); }); - // This is currently broken - see https://github.com/rubensworks/jsonld-streaming-parser.js/issues/112 - it.skip("converting fetch response with custom prefix definition to a store", async () => { + it("converting fetch response with custom prefix definition to a store", async () => { const response = new Response(JSON.stringify(dataWithPrefix)); const quads = [...(await jsonLdResponseToStore(response))]; expect(isomorphic(quads, result)).toBe(true); From eac7d5dfefa8a7ac2a968c5ac6e8ee5880370672 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:07:02 +0100 Subject: [PATCH 27/35] chore: fix code coverage errors --- src/common/common.test.ts | 39 +++++++++++++++++++++++++++++++++++++-- src/parser/jsonld.test.ts | 17 +++++++++++++++++ src/parser/jsonld.ts | 2 +- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 4d1ef819..e61e1aac 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -990,7 +990,7 @@ describe("getVerifiableCredential", () => { ); }); - it("should handle credential subject with a blank node", async () => { + it("should handle credential subject with a blank node and a boolean", async () => { const store = await jsonLdToStore(mockDefaultCredential()); store.add( @@ -1001,6 +1001,38 @@ describe("getVerifiableCredential", () => { ), ); + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicateTrue"), + DataFactory.literal("true", DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")), + ), + ); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicateFalse"), + DataFactory.literal("false", DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")), + ), + ); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://example.org/predicateFalse"), + DataFactory.literal("false", DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")), + ), + ); + + store.add( + DataFactory.quad( + DataFactory.namedNode("https://some.webid.provider/strelka"), + DataFactory.namedNode("https://w3id.org/GConsent#forPurpose"), + DataFactory.namedNode("http://example.org/known/to/be/iri/from/predicate"), + ), + ); + store.add( DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), @@ -1013,7 +1045,7 @@ describe("getVerifiableCredential", () => { await getVerifiableCredentialFromStore(store, "https://some.vc"), ).toMatchObject( Object.assign(mockDefaultCredential(), { - size: 15, + size: 18, // We always re-frame w.r.t to this context "@context": [ "https://www.w3.org/2018/credentials/v1", @@ -1033,6 +1065,9 @@ describe("getVerifiableCredential", () => { "@id": "https://example.org/object", }, "https://example.org/predicateBnode": {}, + "https://example.org/predicateFalse": false, + "https://example.org/predicateTrue": true, + forPurpose: "http://example.org/known/to/be/iri/from/predicate" }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], diff --git a/src/parser/jsonld.test.ts b/src/parser/jsonld.test.ts index 870ef225..705eae90 100644 --- a/src/parser/jsonld.test.ts +++ b/src/parser/jsonld.test.ts @@ -105,6 +105,23 @@ describe("jsonLdResponseToStore", () => { ).toBe(true); }); + it("should error if trying to fetch a remote context when allowContextFetching is disabled", async () => { + const response = new Response( + JSON.stringify({ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "http://example.org/my/remote/context", + ], + id: "https://some.example#credential", + type: ["VerifiableCredential"], + issuer: "https://some.example", + }), + ); + await expect(jsonLdResponseToStore(response, { + allowContextFetching: false + })).rejects.toThrowError('Unexpected context requested [http://example.org/my/remote/context]'); + }); + it("converting fetch response with custom prefix definition to a store", async () => { const response = new Response(JSON.stringify(dataWithPrefix)); const quads = [...(await jsonLdResponseToStore(response))]; diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index 746d36e2..8883a690 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -44,7 +44,7 @@ class CachedFetchDocumentLoader extends FetchDocumentLoader { ...args: ConstructorParameters ) { super(...args); - this.contexts = contexts ? { ...contexts, ...CONTEXTS } : CONTEXTS; + this.contexts = { ...contexts, ...CONTEXTS }; } public async load(url: string): Promise { From ed6d21921cb94e82d5e43c4f7a51a6f072381608 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:30:50 +0100 Subject: [PATCH 28/35] chore: fix lint errors --- src/common/common.test.ts | 21 ++++++++++++++++----- src/common/common.ts | 1 + src/parser/jsonld.test.ts | 10 +++++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/common/common.test.ts b/src/common/common.test.ts index e61e1aac..1dfdfe4b 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -1005,7 +1005,10 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicateTrue"), - DataFactory.literal("true", DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")), + DataFactory.literal( + "true", + DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean"), + ), ), ); @@ -1013,7 +1016,10 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicateFalse"), - DataFactory.literal("false", DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")), + DataFactory.literal( + "false", + DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean"), + ), ), ); @@ -1021,7 +1027,10 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://example.org/predicateFalse"), - DataFactory.literal("false", DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean")), + DataFactory.literal( + "false", + DataFactory.namedNode("http://www.w3.org/2001/XMLSchema#boolean"), + ), ), ); @@ -1029,7 +1038,9 @@ describe("getVerifiableCredential", () => { DataFactory.quad( DataFactory.namedNode("https://some.webid.provider/strelka"), DataFactory.namedNode("https://w3id.org/GConsent#forPurpose"), - DataFactory.namedNode("http://example.org/known/to/be/iri/from/predicate"), + DataFactory.namedNode( + "http://example.org/known/to/be/iri/from/predicate", + ), ), ); @@ -1067,7 +1078,7 @@ describe("getVerifiableCredential", () => { "https://example.org/predicateBnode": {}, "https://example.org/predicateFalse": false, "https://example.org/predicateTrue": true, - forPurpose: "http://example.org/known/to/be/iri/from/predicate" + forPurpose: "http://example.org/known/to/be/iri/from/predicate", }, // Any types outside of those in our VC and Inrupt context are removed type: ["VerifiableCredential"], diff --git a/src/common/common.ts b/src/common/common.ts index 2dee8042..9d8da191 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -681,6 +681,7 @@ export async function getVerifiableCredentialFromStore( const compact = customContext.compactIri(predicate, true); const termContext = customContext.getContextRaw()[compact]; const term = Util.termToValue(object, customContext, { + // FIXME: This could also be @json, xsd:type - so this needs to be more strict // If an `@type` is defined in the context, then the // parser can determine that it is an IRI immediately // and so we don't need to wrap it in an object with an diff --git a/src/parser/jsonld.test.ts b/src/parser/jsonld.test.ts index 705eae90..9006e35d 100644 --- a/src/parser/jsonld.test.ts +++ b/src/parser/jsonld.test.ts @@ -117,9 +117,13 @@ describe("jsonLdResponseToStore", () => { issuer: "https://some.example", }), ); - await expect(jsonLdResponseToStore(response, { - allowContextFetching: false - })).rejects.toThrowError('Unexpected context requested [http://example.org/my/remote/context]'); + await expect( + jsonLdResponseToStore(response, { + allowContextFetching: false, + }), + ).rejects.toThrow( + "Unexpected context requested [http://example.org/my/remote/context]", + ); }); it("converting fetch response with custom prefix definition to a store", async () => { From 670d529ea60193a3ebb0b33600cb2cb4e73815a9 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 22 Oct 2023 17:17:24 +0100 Subject: [PATCH 29/35] chore: remove commented out context --- src/common/common.mock.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/common.mock.ts b/src/common/common.mock.ts index 37372403..0bac7662 100644 --- a/src/common/common.mock.ts +++ b/src/common/common.mock.ts @@ -46,7 +46,6 @@ export type CredentialClaims = VerifiableClaims & { export const defaultVerifiableClaims: VerifiableClaims = { "@context": [ - // { ex: "https://example.org/ns/" }, "https://www.w3.org/2018/credentials/v1", "https://schema.inrupt.com/credentials/v1.jsonld", ], From b62e8d0416e72338180134943b84f0446f8fe7a6 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:44:14 +0100 Subject: [PATCH 30/35] chore: move getSingleObject to global scope --- src/common/common.ts | 54 +++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 9d8da191..c291c932 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -470,6 +470,27 @@ const PROOF_PURPOSE = `${SEC}proofPurpose`; const VERIFICATION_METHOD = `${SEC}verificationMethod`; const PROOF_VALUE = `${SEC}proofValue`; +/** + * @hidden + */ +function getSingleObject( + fullProperty: string, + vcStore: Store, + vc: Term, + subject?: Term, + graph: Term = DF.defaultGraph(), +): Term { + const objects = vcStore.getObjects(subject ?? vc, fullProperty, graph); + + if (objects.length !== 1) { + throw new Error( + `Expected exactly one [${fullProperty}] for the Verifiable Credential ${vc.value}, received: ${objects.length}`, + ); + } + + return objects[0]; +} + /** * @hidden */ @@ -523,22 +544,6 @@ export async function getVerifiableCredentialFromStore( // This allows any context specific to the type of the things that we are re-framing to be applied vcContext = await getVcContext(...typeContexts); - function getSingleObject( - fullProperty: string, - subject?: Term, - graph: Term = DF.defaultGraph(), - ): Term { - const objects = vcStore.getObjects(subject ?? vc, fullProperty, graph); - - if (objects.length !== 1) { - throw new Error( - `Expected exactly one [${fullProperty}] for the Verifiable Credential ${vc.value}, received: ${objects.length}`, - ); - } - - return objects[0]; - } - function getSingleObjectOfTermType( fullProperty: string, subject?: Term, @@ -546,7 +551,7 @@ export async function getVerifiableCredentialFromStore( termType: Term["termType"] = "NamedNode", customContext = vcContext, ) { - const object = getSingleObject(fullProperty, subject, graph); + const object = getSingleObject(fullProperty, vcStore, vc, subject, graph); if (object.termType !== termType) { throw new Error( @@ -565,7 +570,7 @@ export async function getVerifiableCredentialFromStore( subject?: Term, graph?: Term, ) { - const object = getSingleObject(fullProperty, subject, graph); + const object = getSingleObject(fullProperty, vcStore, vc, subject, graph); if (object.termType !== "Literal") { throw new Error( @@ -586,7 +591,7 @@ export async function getVerifiableCredentialFromStore( } // The proof lives within a named graph - const proofGraph = getSingleObject(PROOF); + const proofGraph = getSingleObject(PROOF, vcStore, vc); const proofs = vcStore.getSubjects(null, null, proofGraph); if (proofs.length !== 1) { @@ -681,12 +686,19 @@ export async function getVerifiableCredentialFromStore( const compact = customContext.compactIri(predicate, true); const termContext = customContext.getContextRaw()[compact]; const term = Util.termToValue(object, customContext, { - // FIXME: This could also be @json, xsd:type - so this needs to be more strict // If an `@type` is defined in the context, then the // parser can determine that it is an IRI immediately // and so we don't need to wrap it in an object with an // `@id` entry. - compactIds: termContext && "@type" in termContext, + compactIds: + // Make sure the object of the `@type` keyword is a string + termContext && + "@type" in termContext && + typeof termContext["@type"] === "string" && + // Make sure the object is not a protected keyword that is not `@id` + (!termContext["@type"].startsWith("@") || termContext["@type"] === '@id') && + // Make sure the object is not a datatype + !termContext["@type"].startsWith(XSD), vocab: true, useNativeTypes: true, }); From d7b42b28bf72df3ec77a7f94815685294a3dbd3d Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:45:37 +0100 Subject: [PATCH 31/35] chore: move getSingleObjectOfTermType to global scope --- src/common/common.ts | 77 ++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index c291c932..cd54705b 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -36,6 +36,7 @@ import contentTypeParser from "content-type"; import { Util } from "jsonld-streaming-serializer"; import type { Store, Term } from "n3"; import { DataFactory as DF } from "n3"; +import type { JsonLdContextNormalized } from "jsonld-context-parser"; import { context } from "../parser/contexts"; import VcContext from "../parser/contexts/vc"; import type { ParseOptions } from "../parser/jsonld"; @@ -491,6 +492,29 @@ function getSingleObject( return objects[0]; } +function getSingleObjectOfTermType( + fullProperty: string, + vcStore: Store, + vc: Term, + customContext: JsonLdContextNormalized, + subject?: Term, + graph?: Term, + termType: Term["termType"] = "NamedNode", +) { + const object = getSingleObject(fullProperty, vcStore, vc, subject, graph); + + if (object.termType !== termType) { + throw new Error( + `Expected property [${fullProperty}] of the Verifiable Credential [${vc.value}] to be a ${termType}, received: ${object.termType}`, + ); + } + + // TODO: Make sure that Literals with URIs are correclty handled here + return object.termType === "NamedNode" + ? customContext.compactIri(object.value, true) + : object.value; +} + /** * @hidden */ @@ -544,27 +568,6 @@ export async function getVerifiableCredentialFromStore( // This allows any context specific to the type of the things that we are re-framing to be applied vcContext = await getVcContext(...typeContexts); - function getSingleObjectOfTermType( - fullProperty: string, - subject?: Term, - graph?: Term, - termType: Term["termType"] = "NamedNode", - customContext = vcContext, - ) { - const object = getSingleObject(fullProperty, vcStore, vc, subject, graph); - - if (object.termType !== termType) { - throw new Error( - `Expected property [${fullProperty}] of the Verifiable Credential [${vc.value}] to be a ${termType}, received: ${object.termType}`, - ); - } - - // TODO: Make sure that Literals with URIs are correclty handled here - return object.termType === "NamedNode" - ? customContext.compactIri(object.value, true) - : object.value; - } - function getSingleDateTime( fullProperty: string, subject?: Term, @@ -601,7 +604,14 @@ export async function getVerifiableCredentialFromStore( } const [proof] = proofs; - const proofType = getSingleObjectOfTermType(RDF_TYPE, proof, proofGraph); + const proofType = getSingleObjectOfTermType( + RDF_TYPE, + vcStore, + vc, + vcContext, + proof, + proofGraph, + ); const proposedContextTemp = VcContext["@context"][proofType as keyof (typeof VcContext)["@context"]]; @@ -696,7 +706,8 @@ export async function getVerifiableCredentialFromStore( "@type" in termContext && typeof termContext["@type"] === "string" && // Make sure the object is not a protected keyword that is not `@id` - (!termContext["@type"].startsWith("@") || termContext["@type"] === '@id') && + (!termContext["@type"].startsWith("@") || + termContext["@type"] === "@id") && // Make sure the object is not a datatype !termContext["@type"].startsWith(XSD), vocab: true, @@ -716,7 +727,12 @@ export async function getVerifiableCredentialFromStore( } } - const credentialSubjectTerm = getSingleObjectOfTermType(CREDENTIAL_SUBJECT); + const credentialSubjectTerm = getSingleObjectOfTermType( + CREDENTIAL_SUBJECT, + vcStore, + vc, + proofContext, + ); const res: VerifiableCredential & DatasetCore = { "@context": context, @@ -728,7 +744,7 @@ export async function getVerifiableCredentialFromStore( ...getProperties(DF.namedNode(credentialSubjectTerm)), id: credentialSubjectTerm, }, - issuer: getSingleObjectOfTermType(ISSUER), + issuer: getSingleObjectOfTermType(ISSUER, vcStore, vc, vcContext), issuanceDate: getSingleDateTime(ISSUANCE_DATE), type, proof: { @@ -739,21 +755,28 @@ export async function getVerifiableCredentialFromStore( ), proofPurpose: getSingleObjectOfTermType( PROOF_PURPOSE, + vcStore, + vc, + proofPurposeContext, proof, proofGraph, "NamedNode", - proofPurposeContext, ), type: proofType, verificationMethod: getSingleObjectOfTermType( VERIFICATION_METHOD, + vcStore, + vc, + proofContext, proof, proofGraph, "NamedNode", - proofContext, ), proofValue: getSingleObjectOfTermType( PROOF_VALUE, + vcStore, + vc, + proofContext, proof, proofGraph, "Literal", From 2023b8ae8248a5caec30f02cd356dba5b5e1dc4d Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 22 Oct 2023 20:55:22 +0100 Subject: [PATCH 32/35] chore: refactor writers into global scope --- src/common/common.ts | 261 ++++++++++++++++++++++++------------------- 1 file changed, 144 insertions(+), 117 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index cd54705b..29e736aa 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -34,7 +34,7 @@ import { fetch as uniFetch } from "@inrupt/universal-fetch"; import type { DatasetCore } from "@rdfjs/types"; import contentTypeParser from "content-type"; import { Util } from "jsonld-streaming-serializer"; -import type { Store, Term } from "n3"; +import type { BlankNode, Store, Term } from "n3"; import { DataFactory as DF } from "n3"; import type { JsonLdContextNormalized } from "jsonld-context-parser"; import { context } from "../parser/contexts"; @@ -492,6 +492,9 @@ function getSingleObject( return objects[0]; } +/** + * @hidden + */ function getSingleObjectOfTermType( fullProperty: string, vcStore: Store, @@ -509,12 +512,146 @@ function getSingleObjectOfTermType( ); } + // return writeObject(object, [], fullProperty, vcStore, customContext); // TODO: Make sure that Literals with URIs are correclty handled here return object.termType === "NamedNode" ? customContext.compactIri(object.value, true) : object.value; } +/** + * @hidden + */ +function getProperties(subject: Term, vcStore: Store, vcContext: JsonLdContextNormalized, bnodeId: (id: BlankNode) => string, writtenTerms: string[] = []) { + const object: Record = {}; + + for (const predicate of vcStore.getPredicates( + subject, + null, + DF.defaultGraph(), + )) { + if (predicate.termType !== "NamedNode") { + throw new Error("Predicate must be a namedNode"); + } + + const compact = vcContext.compactIri(predicate.value, true); + const objects = vcStore + .getObjects(subject, predicate, DF.defaultGraph()) + // writeObject and getProperties depend on each other circularly + // eslint-disable-next-line @typescript-eslint/no-use-before-define + .map((obj) => writeObject(obj, writtenTerms, predicate.value, vcStore, vcContext, bnodeId)) + .filter( + (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1, + ); + + if (objects.length === 1) { + [object[compact]] = objects; + } else if (objects.length > 1) { + object[compact] = objects; + } + } + + return object; +} + +/** + * @hidden + */ +function bnodeIdFactory() { + let i = 0; + const data: Record = {}; + return (term: BlankNode) => `_:b${(data[term.value] ??= i += 1)}` +} + +/** + * @hidden + */ +function writeObject( + object: Term, + writtenTerms: string[], + predicate: string, + vcStore: Store, + customContext: JsonLdContextNormalized, + bnodeId: (id: BlankNode) => string +) { + switch (object.termType) { + case "BlankNode": { + const obj = writtenTerms.includes(object.value) + ? {} + : getProperties(object, vcStore, customContext, bnodeId, [...writtenTerms, object.value]); + + // eslint-disable-next-line no-multi-assign + obj["@id"] = bnodeId(object); + return obj; + } + // eslint-disable-next-line no-fallthrough + case "NamedNode": + case "Literal": { + const compact = customContext.compactIri(predicate, true); + const termContext = customContext.getContextRaw()[compact]; + const term = Util.termToValue(object, customContext, { + // If an `@type` is defined in the context, then the + // parser can determine that it is an IRI immediately + // and so we don't need to wrap it in an object with an + // `@id` entry. + compactIds: + // Make sure the object of the `@type` keyword is a string + termContext && + "@type" in termContext && + typeof termContext["@type"] === "string" && + // Make sure the object is not a protected keyword that is not `@id` + (!termContext["@type"].startsWith("@") || + termContext["@type"] === "@id") && + // Make sure the object is not a datatype + !termContext["@type"].startsWith(XSD), + vocab: true, + useNativeTypes: true, + }); + + // Special case: Booleans (any any other native literals for + // that matter) don't need to be wrapped in an object with an + // `@value` key. + if (term["@value"] === true || term["@value"] === false) { + return term["@value"]; + } + return term; + } + default: + throw new Error(`Unexpected term type: ${object.termType}`); + } +} + +/** + * @hidden + */ +function getSingleDateTime( + fullProperty: string, + vcStore: Store, + vc: Term, + subject?: Term, + graph?: Term, +) { + const object = getSingleObject(fullProperty, vcStore, vc, subject, graph); + + if (object.termType !== "Literal") { + throw new Error( + `Expected issuanceDate to be a Literal, received: ${object.termType}`, + ); + } + if (!object.datatype.equals(DF.namedNode(DATE_TIME))) { + throw new Error( + `Expected issuanceDate to have dataType [${DATE_TIME}], received: [${object.datatype.value}]`, + ); + } + + if (Number.isNaN(Date.parse(object.value))) { + throw new Error(`Invalid dateTime in VC [${object.value}]`); + } + + return object.value; +} + + /** * @hidden */ @@ -522,6 +659,7 @@ export async function getVerifiableCredentialFromStore( vcStore: Store, vcUrl: UrlString, ): Promise { + const bnodeId = bnodeIdFactory(); let vcContext = await getVcContext(); const vcs = vcStore.getSubjects( @@ -568,31 +706,6 @@ export async function getVerifiableCredentialFromStore( // This allows any context specific to the type of the things that we are re-framing to be applied vcContext = await getVcContext(...typeContexts); - function getSingleDateTime( - fullProperty: string, - subject?: Term, - graph?: Term, - ) { - const object = getSingleObject(fullProperty, vcStore, vc, subject, graph); - - if (object.termType !== "Literal") { - throw new Error( - `Expected issuanceDate to be a Literal, received: ${object.termType}`, - ); - } - if (!object.datatype.equals(DF.namedNode(DATE_TIME))) { - throw new Error( - `Expected issuanceDate to have dataType [${DATE_TIME}], received: [${object.datatype.value}]`, - ); - } - - if (Number.isNaN(Date.parse(object.value))) { - throw new Error(`Invalid dateTime in VC [${object.value}]`); - } - - return object.value; - } - // The proof lives within a named graph const proofGraph = getSingleObject(PROOF, vcStore, vc); const proofs = vcStore.getSubjects(null, null, proofGraph); @@ -639,99 +752,11 @@ export async function getVerifiableCredentialFromStore( } } - function getProperties(subject: Term, writtenTerms: string[] = []) { - const object: Record = {}; - - for (const predicate of vcStore.getPredicates( - subject, - null, - DF.defaultGraph(), - )) { - if (predicate.termType !== "NamedNode") { - throw new Error("Predicate must be a namedNode"); - } - - const compact = vcContext.compactIri(predicate.value, true); - const objects = vcStore - .getObjects(subject, predicate, DF.defaultGraph()) - // writeObject and getProperties depend on each other circularly - // eslint-disable-next-line @typescript-eslint/no-use-before-define - .map((obj) => writeObject(obj, writtenTerms, predicate.value)) - .filter( - (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1, - ); - - if (objects.length === 1) { - [object[compact]] = objects; - } else if (objects.length > 1) { - object[compact] = objects; - } - } - - return object; - } - - let i = 0; - const data: Record = {}; - - function writeObject( - object: Term, - writtenTerms: string[], - predicate: string, - customContext = vcContext, - ) { - switch (object.termType) { - case "BlankNode": { - const obj = writtenTerms.includes(object.value) - ? {} - : getProperties(object, [...writtenTerms, object.value]); - - // eslint-disable-next-line no-multi-assign - obj["@id"] = `_:b${(data[object.value] ??= i += 1)}`; - return obj; - } - // eslint-disable-next-line no-fallthrough - case "NamedNode": - case "Literal": { - const compact = customContext.compactIri(predicate, true); - const termContext = customContext.getContextRaw()[compact]; - const term = Util.termToValue(object, customContext, { - // If an `@type` is defined in the context, then the - // parser can determine that it is an IRI immediately - // and so we don't need to wrap it in an object with an - // `@id` entry. - compactIds: - // Make sure the object of the `@type` keyword is a string - termContext && - "@type" in termContext && - typeof termContext["@type"] === "string" && - // Make sure the object is not a protected keyword that is not `@id` - (!termContext["@type"].startsWith("@") || - termContext["@type"] === "@id") && - // Make sure the object is not a datatype - !termContext["@type"].startsWith(XSD), - vocab: true, - useNativeTypes: true, - }); - - // Special case: Booleans (any any other native literals for - // that matter) don't need to be wrapped in an object with an - // `@value` key. - if (term["@value"] === true || term["@value"] === false) { - return term["@value"]; - } - return term; - } - default: - throw new Error(`Unexpected term type: ${object.termType}`); - } - } - const credentialSubjectTerm = getSingleObjectOfTermType( CREDENTIAL_SUBJECT, vcStore, vc, - proofContext, + proofContext ); const res: VerifiableCredential & DatasetCore = { @@ -741,15 +766,17 @@ export async function getVerifiableCredentialFromStore( // we do not support this // https://www.w3.org/TR/vc-data-model/#example-specifying-multiple-subjects-in-a-verifiable-credential credentialSubject: { - ...getProperties(DF.namedNode(credentialSubjectTerm)), + ...getProperties(DF.namedNode(credentialSubjectTerm), vcStore, vcContext, bnodeId), id: credentialSubjectTerm, }, issuer: getSingleObjectOfTermType(ISSUER, vcStore, vc, vcContext), - issuanceDate: getSingleDateTime(ISSUANCE_DATE), + issuanceDate: getSingleDateTime(ISSUANCE_DATE, vcStore, vc), type, proof: { created: getSingleDateTime( "http://purl.org/dc/terms/created", + vcStore, + vc, proof, proofGraph, ), From c2ea62631b6a79593cd7a7cbd2c0845b0c685de0 Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 22 Oct 2023 22:36:56 +0100 Subject: [PATCH 33/35] chore: code cleanup --- src/common/common.ts | 182 +++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 94 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 29e736aa..6a105947 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -499,7 +499,6 @@ function getSingleObjectOfTermType( fullProperty: string, vcStore: Store, vc: Term, - customContext: JsonLdContextNormalized, subject?: Term, graph?: Term, termType: Term["termType"] = "NamedNode", @@ -512,55 +511,7 @@ function getSingleObjectOfTermType( ); } - // return writeObject(object, [], fullProperty, vcStore, customContext); - // TODO: Make sure that Literals with URIs are correclty handled here - return object.termType === "NamedNode" - ? customContext.compactIri(object.value, true) - : object.value; -} - -/** - * @hidden - */ -function getProperties(subject: Term, vcStore: Store, vcContext: JsonLdContextNormalized, bnodeId: (id: BlankNode) => string, writtenTerms: string[] = []) { - const object: Record = {}; - - for (const predicate of vcStore.getPredicates( - subject, - null, - DF.defaultGraph(), - )) { - if (predicate.termType !== "NamedNode") { - throw new Error("Predicate must be a namedNode"); - } - - const compact = vcContext.compactIri(predicate.value, true); - const objects = vcStore - .getObjects(subject, predicate, DF.defaultGraph()) - // writeObject and getProperties depend on each other circularly - // eslint-disable-next-line @typescript-eslint/no-use-before-define - .map((obj) => writeObject(obj, writtenTerms, predicate.value, vcStore, vcContext, bnodeId)) - .filter( - (obj) => typeof obj !== "object" || Object.keys(obj).length >= 1, - ); - - if (objects.length === 1) { - [object[compact]] = objects; - } else if (objects.length > 1) { - object[compact] = objects; - } - } - - return object; -} - -/** - * @hidden - */ -function bnodeIdFactory() { - let i = 0; - const data: Record = {}; - return (term: BlankNode) => `_:b${(data[term.value] ??= i += 1)}` + return object.value; } /** @@ -572,13 +523,16 @@ function writeObject( predicate: string, vcStore: Store, customContext: JsonLdContextNormalized, - bnodeId: (id: BlankNode) => string + bnodeId: (id: BlankNode) => string, ) { switch (object.termType) { case "BlankNode": { const obj = writtenTerms.includes(object.value) ? {} - : getProperties(object, vcStore, customContext, bnodeId, [...writtenTerms, object.value]); + : getProperties(object, vcStore, customContext, bnodeId, [ + ...writtenTerms, + object.value, + ]); // eslint-disable-next-line no-multi-assign obj["@id"] = bnodeId(object); @@ -594,16 +548,7 @@ function writeObject( // parser can determine that it is an IRI immediately // and so we don't need to wrap it in an object with an // `@id` entry. - compactIds: - // Make sure the object of the `@type` keyword is a string - termContext && - "@type" in termContext && - typeof termContext["@type"] === "string" && - // Make sure the object is not a protected keyword that is not `@id` - (!termContext["@type"].startsWith("@") || - termContext["@type"] === "@id") && - // Make sure the object is not a datatype - !termContext["@type"].startsWith(XSD), + compactIds: termContext && "@type" in termContext, vocab: true, useNativeTypes: true, }); @@ -621,6 +566,64 @@ function writeObject( } } +/** + * @hidden + */ +function getProperties( + subject: Term, + vcStore: Store, + vcContext: JsonLdContextNormalized, + bnodeId: (id: BlankNode) => string, + writtenTerms: string[] = [], +) { + const object: Record = {}; + + for (const predicate of vcStore.getPredicates( + subject, + null, + DF.defaultGraph(), + )) { + if (predicate.termType !== "NamedNode") { + throw new Error("Predicate must be a namedNode"); + } + + const compact = vcContext.compactIri(predicate.value, true); + const objects = vcStore + .getObjects(subject, predicate, DF.defaultGraph()) + // writeObject and getProperties depend on each other circularly + // eslint-disable-next-line @typescript-eslint/no-use-before-define + .map((obj) => + writeObject( + obj, + writtenTerms, + predicate.value, + vcStore, + vcContext, + bnodeId, + ), + ) + .filter((obj) => typeof obj !== "object" || Object.keys(obj).length >= 1); + + if (objects.length === 1) { + [object[compact]] = objects; + } else if (objects.length > 1) { + object[compact] = objects; + } + } + + return object; +} + +/** + * @hidden + */ +function bnodeIdFactory() { + let i = 0; + const data: Record = {}; + // eslint-disable-next-line no-return-assign, no-multi-assign + return (term: BlankNode) => `_:b${(data[term.value] ??= i += 1)}`; +} + /** * @hidden */ @@ -651,7 +654,6 @@ function getSingleDateTime( return object.value; } - /** * @hidden */ @@ -721,13 +723,17 @@ export async function getVerifiableCredentialFromStore( RDF_TYPE, vcStore, vc, - vcContext, proof, proofGraph, ); const proposedContextTemp = - VcContext["@context"][proofType as keyof (typeof VcContext)["@context"]]; + VcContext["@context"][ + vcContext.compactIri( + proofType, + true, + ) as keyof (typeof VcContext)["@context"] + ]; const proposedContext = typeof proposedContextTemp === "object" && "@context" in proposedContextTemp && @@ -756,9 +762,9 @@ export async function getVerifiableCredentialFromStore( CREDENTIAL_SUBJECT, vcStore, vc, - proofContext ); + const proofArgs = [vcStore, vc, proof, proofGraph] as const; const res: VerifiableCredential & DatasetCore = { "@context": context, id: vc.value, @@ -766,46 +772,34 @@ export async function getVerifiableCredentialFromStore( // we do not support this // https://www.w3.org/TR/vc-data-model/#example-specifying-multiple-subjects-in-a-verifiable-credential credentialSubject: { - ...getProperties(DF.namedNode(credentialSubjectTerm), vcStore, vcContext, bnodeId), + ...getProperties( + DF.namedNode(credentialSubjectTerm), + vcStore, + vcContext, + bnodeId, + ), id: credentialSubjectTerm, }, - issuer: getSingleObjectOfTermType(ISSUER, vcStore, vc, vcContext), + issuer: getSingleObjectOfTermType(ISSUER, vcStore, vc), issuanceDate: getSingleDateTime(ISSUANCE_DATE, vcStore, vc), type, proof: { created: getSingleDateTime( "http://purl.org/dc/terms/created", - vcStore, - vc, - proof, - proofGraph, + ...proofArgs, ), - proofPurpose: getSingleObjectOfTermType( - PROOF_PURPOSE, - vcStore, - vc, - proofPurposeContext, - proof, - proofGraph, - "NamedNode", + proofPurpose: proofPurposeContext.compactIri( + getSingleObjectOfTermType(PROOF_PURPOSE, ...proofArgs), + true, ), - type: proofType, - verificationMethod: getSingleObjectOfTermType( - VERIFICATION_METHOD, - vcStore, - vc, - proofContext, - proof, - proofGraph, - "NamedNode", + type: proofContext.compactIri(proofType, true), + verificationMethod: proofContext.compactIri( + getSingleObjectOfTermType(VERIFICATION_METHOD, ...proofArgs), + true, ), proofValue: getSingleObjectOfTermType( PROOF_VALUE, - vcStore, - vc, - proofContext, - proof, - proofGraph, + ...proofArgs, "Literal", ), }, From a96de18262d7845817218f91f621569783fa1d1b Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Sun, 22 Oct 2023 22:39:33 +0100 Subject: [PATCH 34/35] chore: improve naming --- src/common/common.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/common/common.ts b/src/common/common.ts index 6a105947..ba7c22e6 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -523,19 +523,19 @@ function writeObject( predicate: string, vcStore: Store, customContext: JsonLdContextNormalized, - bnodeId: (id: BlankNode) => string, + createBnodeId: (id: BlankNode) => string, ) { switch (object.termType) { case "BlankNode": { const obj = writtenTerms.includes(object.value) ? {} - : getProperties(object, vcStore, customContext, bnodeId, [ + : getProperties(object, vcStore, customContext, createBnodeId, [ ...writtenTerms, object.value, ]); // eslint-disable-next-line no-multi-assign - obj["@id"] = bnodeId(object); + obj["@id"] = createBnodeId(object); return obj; } // eslint-disable-next-line no-fallthrough @@ -573,7 +573,7 @@ function getProperties( subject: Term, vcStore: Store, vcContext: JsonLdContextNormalized, - bnodeId: (id: BlankNode) => string, + createBnodeId: (id: BlankNode) => string, writtenTerms: string[] = [], ) { const object: Record = {}; @@ -599,7 +599,7 @@ function getProperties( predicate.value, vcStore, vcContext, - bnodeId, + createBnodeId, ), ) .filter((obj) => typeof obj !== "object" || Object.keys(obj).length >= 1); @@ -617,7 +617,7 @@ function getProperties( /** * @hidden */ -function bnodeIdFactory() { +function createBnodeIdFactory() { let i = 0; const data: Record = {}; // eslint-disable-next-line no-return-assign, no-multi-assign @@ -661,7 +661,7 @@ export async function getVerifiableCredentialFromStore( vcStore: Store, vcUrl: UrlString, ): Promise { - const bnodeId = bnodeIdFactory(); + const createBnodeId = createBnodeIdFactory(); let vcContext = await getVcContext(); const vcs = vcStore.getSubjects( @@ -776,7 +776,7 @@ export async function getVerifiableCredentialFromStore( DF.namedNode(credentialSubjectTerm), vcStore, vcContext, - bnodeId, + createBnodeId, ), id: credentialSubjectTerm, }, From b108867e2cccc5e7c6215d4ef9e30918ae13397e Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Tue, 24 Oct 2023 18:11:19 +0100 Subject: [PATCH 35/35] chore: WIP re-serialize issuer calls --- src/common/common.test.ts | 20 ++++- src/common/common.ts | 15 +++- src/issue/issue.test.ts | 20 ++++- src/issue/issue.ts | 30 +++---- src/parser/contexts/data-integrity.ts | 94 ++++++++++++++++++++ src/parser/contexts/ed25519-2020.ts | 113 +++++++++++++++++++++++++ src/parser/contexts/index.ts | 13 +++ src/parser/contexts/inrupt-vc.ts | 84 ++++++++++++++++++ src/parser/contexts/revocation-list.ts | 68 +++++++++++++++ src/parser/contexts/status-list.ts | 68 +++++++++++++++ src/parser/jsonld.ts | 4 +- 11 files changed, 506 insertions(+), 23 deletions(-) create mode 100644 src/parser/contexts/data-integrity.ts create mode 100644 src/parser/contexts/ed25519-2020.ts create mode 100644 src/parser/contexts/inrupt-vc.ts create mode 100644 src/parser/contexts/revocation-list.ts create mode 100644 src/parser/contexts/status-list.ts diff --git a/src/common/common.test.ts b/src/common/common.test.ts index 1dfdfe4b..b5f78411 100644 --- a/src/common/common.test.ts +++ b/src/common/common.test.ts @@ -31,6 +31,7 @@ import { getVerifiableCredentialFromStore, isVerifiableCredential, isVerifiablePresentation, + normalizeVc, } from "./common"; import { defaultCredentialClaims, @@ -55,6 +56,13 @@ jest.mock("@inrupt/universal-fetch", () => { }; }); +describe("normalizeVc", () => { + it("returns the same object", () => { + const obj = {}; + expect(normalizeVc(obj)).toEqual(obj); + }); +}); + describe("isVerifiableCredential", () => { it("returns true if all the expected fields are present in the credential", () => { expect(isVerifiableCredential(mockDefaultCredential())).toBe(true); @@ -647,7 +655,7 @@ describe("getVerifiableCredential", () => { fetch: mockedFetch, }); - expect(vc).toMatchObject({ + const result = { ...mocked, credentialSubject: { ...mocked.credentialSubject, @@ -657,6 +665,7 @@ describe("getVerifiableCredential", () => { }, // This is how blank nodes are represented "https://example.org/my/predicate/i": { + "@id": "_:b1", "https://example.org/my/predicate": { "@value": "object", }, @@ -666,7 +675,14 @@ describe("getVerifiableCredential", () => { // Unknown types like http://example.org/spaceDog are excluded "VerifiableCredential", ], - }); + }; + + // Since we have dataset properties in vc it should match the result + // but won't equal + expect(vc).toMatchObject(result); + // However we DO NOT want these properties showing up when we stringify + // the VC + expect(JSON.parse(JSON.stringify(vc))).toEqual(result); }); it("should error if more than 2 subjects in proof graph", async () => { diff --git a/src/common/common.ts b/src/common/common.ts index ba7c22e6..768f4d90 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -535,7 +535,7 @@ function writeObject( ]); // eslint-disable-next-line no-multi-assign - obj["@id"] = createBnodeId(object); + // obj["@id"] = createBnodeId(object); return obj; } // eslint-disable-next-line no-fallthrough @@ -826,6 +826,19 @@ export async function getVerifiableCredentialFromStore( get size() { return vcStore.size; }, + // For backwards compatibility the dataset properties + // SHOULD NOT be included when we JSON.stringify the object + toJSON() { + return { + "@context": this["@context"], + id: this.id, + credentialSubject: this.credentialSubject, + issuer: this.issuer, + issuanceDate: this.issuanceDate, + type: this.type, + proof: this.proof, + }; + }, }; return res; diff --git a/src/issue/issue.test.ts b/src/issue/issue.test.ts index 6229701b..51082b76 100644 --- a/src/issue/issue.test.ts +++ b/src/issue/issue.test.ts @@ -113,7 +113,10 @@ describe("issueVerifiableCredential", () => { const mockedFetch = jest .fn<(typeof UniversalFetch)["fetch"]>() .mockResolvedValueOnce( - new Response(JSON.stringify(mockDefaultCredential()), { status: 201 }), + new Response(JSON.stringify(mockDefaultCredential()), { + status: 201, + headers: new Headers([["content-type", "application/ld+json"]]), + }), ); await expect( issueVerifiableCredential( @@ -122,7 +125,19 @@ describe("issueVerifiableCredential", () => { { "@context": ["https://some.context"] }, { fetch: mockedFetch }, ), - ).resolves.toEqual(mockDefaultCredential()); + ).resolves.toMatchObject({ + ...mockDefaultCredential(), + credentialSubject: { + ...mockDefaultCredential().credentialSubject, + "https://example.org/ns/passengerOf": { + "@value": "https://example.org/ns/Korabl-Sputnik2", + }, + "https://example.org/ns/status": { + "@value": "https://example.org/ns/GoodDog", + }, + }, + type: ["VerifiableCredential"], + }); }); it("sends a request to the specified issuer", async () => { @@ -396,6 +411,7 @@ describe("issueVerifiableCredential", () => { const mockedFetch = jest.fn().mockResolvedValueOnce( new Response(JSON.stringify(mockedVc), { status: 201, + headers: new Headers([["content-type", "application/json"]]), }), ); const resultVc = await issueVerifiableCredential( diff --git a/src/issue/issue.ts b/src/issue/issue.ts index c8a1fd13..9a21c16d 100644 --- a/src/issue/issue.ts +++ b/src/issue/issue.ts @@ -25,13 +25,13 @@ import { fetch as fallbackFetch } from "@inrupt/universal-fetch"; +import type { DatasetCore } from "@rdfjs/types"; import type { Iri, JsonLd, VerifiableCredential } from "../common/common"; import { - isVerifiableCredential, concatenateContexts, defaultContext, defaultCredentialTypes, - normalizeVc, + getVerifiableCredentialFromResponse, } from "../common/common"; type OptionsType = { @@ -47,7 +47,7 @@ async function internal_issueVerifiableCredential( subjectClaims: JsonLd, credentialClaims?: JsonLd, options?: OptionsType, -): Promise { +): Promise { const internalOptions = { ...options }; if (internalOptions.fetch === undefined) { internalOptions.fetch = fallbackFetch; @@ -101,17 +101,15 @@ async function internal_issueVerifiableCredential( `The VC issuing endpoint [${issuerEndpoint}] could not successfully issue a VC: ${response.status} ${response.statusText}`, ); } - const jsonData = normalizeVc(await response.json()); - if (isVerifiableCredential(jsonData)) { - return jsonData; + + try { + // FIXME: Check response.url as the second arg + return await getVerifiableCredentialFromResponse(response, response.url); + } catch (e) { + throw new Error( + `The VC issuing endpoint [${issuerEndpoint}] returned an unexpected object: ${e}`, + ); } - throw new Error( - `The VC issuing endpoint [${issuerEndpoint}] returned an unexpected object: ${JSON.stringify( - jsonData, - null, - " ", - )}`, - ); } /** @@ -134,7 +132,7 @@ export async function issueVerifiableCredential( subjectClaims: JsonLd, credentialClaims?: JsonLd, options?: OptionsType, -): Promise; +): Promise; /** * @deprecated Please remove the `subjectId` parameter */ @@ -144,7 +142,7 @@ export async function issueVerifiableCredential( subjectClaims: JsonLd, credentialClaims?: JsonLd, options?: OptionsType, -): Promise; +): Promise; // The signature of the implementation here is a bit confusing, but it avoid // breaking changes until we remove the `subjectId` completely from the API export async function issueVerifiableCredential( @@ -153,7 +151,7 @@ export async function issueVerifiableCredential( subjectOrCredentialClaims: JsonLd | undefined, credentialClaimsOrOptions?: JsonLd | OptionsType, options?: OptionsType, -): Promise { +): Promise { if (typeof subjectIdOrClaims === "string") { // The function has been called with the deprecated signature, and the // subjectOrCredentialClaims parameter should be ignored. diff --git a/src/parser/contexts/data-integrity.ts b/src/parser/contexts/data-integrity.ts new file mode 100644 index 00000000..c9898768 --- /dev/null +++ b/src/parser/contexts/data-integrity.ts @@ -0,0 +1,94 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// +export default { + "@context": { + id: "@id", + type: "@type", + "@protected": true, + proof: { + "@id": "https://w3id.org/security#proof", + "@type": "@id", + "@container": "@graph", + }, + DataIntegrityProof: { + "@id": "https://w3id.org/security#DataIntegrityProof", + "@context": { + "@protected": true, + id: "@id", + type: "@type", + challenge: "https://w3id.org/security#challenge", + created: { + "@id": "http://purl.org/dc/terms/created", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + }, + domain: "https://w3id.org/security#domain", + expires: { + "@id": "https://w3id.org/security#expiration", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + }, + nonce: "https://w3id.org/security#nonce", + proofPurpose: { + "@id": "https://w3id.org/security#proofPurpose", + "@type": "@vocab", + "@context": { + "@protected": true, + id: "@id", + type: "@type", + assertionMethod: { + "@id": "https://w3id.org/security#assertionMethod", + "@type": "@id", + "@container": "@set", + }, + authentication: { + "@id": "https://w3id.org/security#authenticationMethod", + "@type": "@id", + "@container": "@set", + }, + capabilityInvocation: { + "@id": "https://w3id.org/security#capabilityInvocationMethod", + "@type": "@id", + "@container": "@set", + }, + capabilityDelegation: { + "@id": "https://w3id.org/security#capabilityDelegationMethod", + "@type": "@id", + "@container": "@set", + }, + keyAgreement: { + "@id": "https://w3id.org/security#keyAgreementMethod", + "@type": "@id", + "@container": "@set", + }, + }, + }, + cryptosuite: "https://w3id.org/security#cryptosuite", + proofValue: { + "@id": "https://w3id.org/security#proofValue", + "@type": "https://w3id.org/security#multibase", + }, + verificationMethod: { + "@id": "https://w3id.org/security#verificationMethod", + "@type": "@id", + }, + }, + }, + }, +}; diff --git a/src/parser/contexts/ed25519-2020.ts b/src/parser/contexts/ed25519-2020.ts new file mode 100644 index 00000000..b65eb596 --- /dev/null +++ b/src/parser/contexts/ed25519-2020.ts @@ -0,0 +1,113 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// +export default { + "@context": { + id: "@id", + type: "@type", + "@protected": true, + proof: { + "@id": "https://w3id.org/security#proof", + "@type": "@id", + "@container": "@graph", + }, + Ed25519VerificationKey2020: { + "@id": "https://w3id.org/security#Ed25519VerificationKey2020", + "@context": { + "@protected": true, + id: "@id", + type: "@type", + controller: { + "@id": "https://w3id.org/security#controller", + "@type": "@id", + }, + revoked: { + "@id": "https://w3id.org/security#revoked", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + }, + publicKeyMultibase: { + "@id": "https://w3id.org/security#publicKeyMultibase", + "@type": "https://w3id.org/security#multibase", + }, + }, + }, + Ed25519Signature2020: { + "@id": "https://w3id.org/security#Ed25519Signature2020", + "@context": { + "@protected": true, + id: "@id", + type: "@type", + challenge: "https://w3id.org/security#challenge", + created: { + "@id": "http://purl.org/dc/terms/created", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + }, + domain: "https://w3id.org/security#domain", + expires: { + "@id": "https://w3id.org/security#expiration", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + }, + nonce: "https://w3id.org/security#nonce", + proofPurpose: { + "@id": "https://w3id.org/security#proofPurpose", + "@type": "@vocab", + "@context": { + "@protected": true, + id: "@id", + type: "@type", + assertionMethod: { + "@id": "https://w3id.org/security#assertionMethod", + "@type": "@id", + "@container": "@set", + }, + authentication: { + "@id": "https://w3id.org/security#authenticationMethod", + "@type": "@id", + "@container": "@set", + }, + capabilityInvocation: { + "@id": "https://w3id.org/security#capabilityInvocationMethod", + "@type": "@id", + "@container": "@set", + }, + capabilityDelegation: { + "@id": "https://w3id.org/security#capabilityDelegationMethod", + "@type": "@id", + "@container": "@set", + }, + keyAgreement: { + "@id": "https://w3id.org/security#keyAgreementMethod", + "@type": "@id", + "@container": "@set", + }, + }, + }, + proofValue: { + "@id": "https://w3id.org/security#proofValue", + "@type": "https://w3id.org/security#multibase", + }, + verificationMethod: { + "@id": "https://w3id.org/security#verificationMethod", + "@type": "@id", + }, + }, + }, + }, +}; diff --git a/src/parser/contexts/index.ts b/src/parser/contexts/index.ts index 10e032d9..384f8ded 100644 --- a/src/parser/contexts/index.ts +++ b/src/parser/contexts/index.ts @@ -20,11 +20,24 @@ // import VC from "./vc"; import Inrupt from "./inrupt"; +import vc from "./inrupt-vc"; +import integrity from "./data-integrity"; +import ed25519 from "./ed25519-2020"; +import revocation from "./revocation-list"; +import statusList from "./status-list"; const contextDefinitions = { "https://www.w3.org/2018/credentials/v1": VC, "https://schema.inrupt.com/credentials/v1.jsonld": Inrupt, } as const; +export const cachedContexts = { + "https://vc.inrupt.com/credentials/v1": vc, + "https://w3id.org/security/data-integrity/v1": integrity, + "https://w3id.org/vc-revocation-list-2020/v1": revocation, + "https://w3id.org/vc/status-list/2021/v1": statusList, + "https://w3id.org/security/suites/ed25519-2020/v1": ed25519, +}; + export const context = Object.keys(contextDefinitions); export default contextDefinitions; diff --git a/src/parser/contexts/inrupt-vc.ts b/src/parser/contexts/inrupt-vc.ts new file mode 100644 index 00000000..56ed156c --- /dev/null +++ b/src/parser/contexts/inrupt-vc.ts @@ -0,0 +1,84 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// +export default { + "@context": { + "@version": 1.1, + "@protected": true, + ldp: "http://www.w3.org/ns/ldp#", + acl: "http://www.w3.org/ns/auth/acl#", + gc: "https://w3id.org/GConsent#", + vc: "http://www.w3.org/ns/solid/vc#", + xsd: "http://www.w3.org/2001/XMLSchema#", + issuerService: { "@id": "vc:issuerService", "@type": "@id" }, + statusService: { "@id": "vc:statusService", "@type": "@id" }, + verifierService: { "@id": "vc:verifierService", "@type": "@id" }, + derivationService: { "@id": "vc:derivationService", "@type": "@id" }, + proofService: { "@id": "vc:proofService", "@type": "@id" }, + availabilityService: { "@id": "vc:availabilityService", "@type": "@id" }, + submissionService: { "@id": "vc:submissionService", "@type": "@id" }, + supportedSignatureTypes: { + "@id": "vc:supportedSignatureTypes", + "@type": "@id", + }, + include: { "@id": "vc:include", "@type": "@id" }, + SolidAccessGrant: "vc:SolidAccessGrant", + SolidAccessRequest: "vc:SolidAccessRequest", + ExpiredVerifiableCredential: "vc:ExpiredVerifiableCredential", + inbox: { "@id": "ldp:inbox", "@type": "@id" }, + Read: "acl:Read", + Write: "acl:Write", + Append: "acl:Append", + mode: { "@id": "acl:mode", "@type": "@vocab" }, + Consent: "gc:Consent", + ConsentStatusExpired: "gc:ConsentStatusExpired", + ConsentStatusExplicitlyGiven: "gc:ConsentStatusExplicitlyGiven", + ConsentStatusGivenByDelegation: "gc:ConsentStatusGivenByDelegation", + ConsentStatusImplicitlyGiven: "gc:ConsentStatusImplicitlyGiven", + ConsentStatusInvalidated: "gc:ConsentStatusInvalidated", + ConsentStatusNotGiven: "gc:ConsentStatusNotGiven", + ConsentStatusRefused: "gc:ConsentStatusRefused", + ConsentStatusRequested: "gc:ConsentStatusRequested", + ConsentStatusUnknown: "gc:ConsentStatusUnknown", + ConsentStatusWithdrawn: "gc:ConsentStatusWithdrawn", + forPersonalData: { "@id": "gc:forPersonalData", "@type": "@id" }, + forProcessing: { "@id": "gc:forProcessing", "@type": "@id" }, + forPurpose: { "@id": "gc:forPurpose", "@type": "@id" }, + hasConsent: { "@id": "gc:hasConsent", "@type": "@id" }, + hasContext: { "@id": "gc:hasContext", "@type": "@id" }, + hasStatus: { "@id": "gc:hasStatus", "@type": "@vocab" }, + inMedium: { "@id": "gc:inMedium", "@type": "@id" }, + isConsentForDataSubject: { + "@id": "gc:isConsentForDataSubject", + "@type": "@id", + }, + isProvidedTo: { "@id": "gc:isProvidedTo", "@type": "@id" }, + isProvidedToPerson: { "@id": "gc:isProvidedToPerson", "@type": "@id" }, + isProvidedToController: { + "@id": "gc:isProvidedToController", + "@type": "@id", + }, + providedConsent: { "@id": "gc:providedConsent", "@type": "@id" }, + inherit: { + "@id": "urn:uuid:71ab2f68-a68b-4452-b968-dd23e0570227", + "@type": "xsd:boolean", + }, + }, +}; diff --git a/src/parser/contexts/revocation-list.ts b/src/parser/contexts/revocation-list.ts new file mode 100644 index 00000000..08a7861b --- /dev/null +++ b/src/parser/contexts/revocation-list.ts @@ -0,0 +1,68 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// +export default { + "@context": { + "@protected": true, + RevocationList2020Credential: { + "@id": + "https://w3id.org/vc-revocation-list-2020#RevocationList2020Credential", + "@context": { + "@protected": true, + + id: "@id", + type: "@type", + + description: "http://schema.org/description", + name: "http://schema.org/name", + }, + }, + RevocationList2020: { + "@id": "https://w3id.org/vc-revocation-list-2020#RevocationList2020", + "@context": { + "@protected": true, + + id: "@id", + type: "@type", + + encodedList: "https://w3id.org/vc-revocation-list-2020#encodedList", + }, + }, + + RevocationList2020Status: { + "@id": + "https://w3id.org/vc-revocation-list-2020#RevocationList2020Status", + "@context": { + "@protected": true, + + id: "@id", + type: "@type", + + revocationListCredential: { + "@id": + "https://w3id.org/vc-revocation-list-2020#revocationListCredential", + "@type": "@id", + }, + revocationListIndex: + "https://w3id.org/vc-revocation-list-2020#revocationListIndex", + }, + }, + }, +}; diff --git a/src/parser/contexts/status-list.ts b/src/parser/contexts/status-list.ts new file mode 100644 index 00000000..24653e81 --- /dev/null +++ b/src/parser/contexts/status-list.ts @@ -0,0 +1,68 @@ +// +// Copyright Inrupt Inc. +// +// 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. +// +export default { + "@context": { + "@protected": true, + + StatusList2021Credential: { + "@id": "https://w3id.org/vc/status-list#StatusList2021Credential", + "@context": { + "@protected": true, + + id: "@id", + type: "@type", + + description: "http://schema.org/description", + name: "http://schema.org/name", + }, + }, + + StatusList2021: { + "@id": "https://w3id.org/vc/status-list#StatusList2021", + "@context": { + "@protected": true, + + id: "@id", + type: "@type", + + statusPurpose: "https://w3id.org/vc/status-list#statusPurpose", + encodedList: "https://w3id.org/vc/status-list#encodedList", + }, + }, + + StatusList2021Entry: { + "@id": "https://w3id.org/vc/status-list#StatusList2021Entry", + "@context": { + "@protected": true, + + id: "@id", + type: "@type", + + statusPurpose: "https://w3id.org/vc/status-list#statusPurpose", + statusListIndex: "https://w3id.org/vc/status-list#statusListIndex", + statusListCredential: { + "@id": "https://w3id.org/vc/status-list#statusListCredential", + "@type": "@id", + }, + }, + }, + }, +}; diff --git a/src/parser/jsonld.ts b/src/parser/jsonld.ts index 8883a690..5851aef3 100644 --- a/src/parser/jsonld.ts +++ b/src/parser/jsonld.ts @@ -29,7 +29,7 @@ import type { import { ContextParser, FetchDocumentLoader } from "jsonld-context-parser"; import { JsonLdParser } from "jsonld-streaming-parser"; import { Store } from "n3"; -import CONTEXTS from "./contexts"; +import CONTEXTS, { cachedContexts } from "./contexts"; import type { JsonLd } from "../common/common"; /** @@ -44,7 +44,7 @@ class CachedFetchDocumentLoader extends FetchDocumentLoader { ...args: ConstructorParameters ) { super(...args); - this.contexts = { ...contexts, ...CONTEXTS }; + this.contexts = { ...contexts, ...cachedContexts, ...CONTEXTS }; } public async load(url: string): Promise {