diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c6d839e..58cbc1a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,7 +46,10 @@ jobs: - name: Install Dependencies run: yarn install --frozen-lockfile --network-concurrency 1 - - name: Build & Test + - name: Build + run: yarn build + + - name: Test run: yarn test # Run lint after testing for more info diff --git a/jest.config.js b/jest.config.ts similarity index 89% rename from jest.config.js rename to jest.config.ts index 1a5935b..7b69fbc 100644 --- a/jest.config.js +++ b/jest.config.ts @@ -1,4 +1,4 @@ -module.exports = { // eslint-disable-line +export default { transform: { ".(ts|tsx)": "ts-jest" }, diff --git a/package.json b/package.json index f2473a8..46656b5 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,10 @@ { "name": "ucans", - "version": "0.10.0", "description": "Typescript implementation of UCANs", "author": "Daniel Holmgren ", "repository": { "type": "git", - "url": "https://github.com/fission-suite/ucan" + "url": "https://github.com/ucan-wg/ts-ucan" }, "homepage": "https://guide.fission.codes", "license": "Apache-2.0", @@ -13,75 +12,15 @@ "node": ">=15" }, "scripts": { - "prebuild": "rimraf dist", - "build": "yarn run dist", - "dev": "tsc --watch --module commonjs --outDir ./dist/cjs/ --sourceMap", - "dist": "yarn run dist:prep && yarn run dist:src && yarn run dist:cjs && yarn run dist:esm && yarn run dist:types && yarn run dist:pkg", - "dist:cjs": "tsc --project ./dist/ --module commonjs --outDir ./dist/cjs/ --sourceMap", - "dist:esm": "tsc --project ./dist/ --module es2020 --outDir ./dist/esm/ --sourceMap", - "dist:pkg": "node ./scripts/package.js", - "dist:prep": "copyfiles --error tsconfig.json ./dist/", - "dist:src": "copyfiles --error --up 1 \"./src/**/*\" ./dist/src/", - "dist:types": "tsc --project ./dist/ --emitDeclarationOnly --declaration --declarationDir ./dist/types/", - "lint": "eslint src/**/*.ts src/*.ts tests/**/*.ts tests/*.ts", - "prepare": "yarn build", - "publish-alpha": "yarn publish --tag alpha", - "publish-stable": "yarn publish --tag latest", - "test": "jest", - "test:watch": "jest --watch" + "build": "yarn workspace @ucans/core build && yarn workspace @ucans/default-plugins build && yarn workspace @ucans/ucans build", + "test": "yarn workspace @ucans/core test && yarn workspace @ucans/default-plugins test && yarn workspace @ucans/ucans test", + "lint": "yarn workspace @ucans/core lint && yarn workspace @ucans/default-plugins lint && yarn workspace @ucans/ucans lint" }, - "exports": { - ".": { - "import": "./dist/esm/index.js", - "require": "./dist/cjs/index.js", - "types": "./dist/types/index.d.ts" - }, - "./*.js": { - "import": "./dist/esm/*.js", - "require": "./dist/cjs/*.js", - "types": "./dist/types/*.d.ts" - }, - "./*": { - "import": "./dist/esm/*.js", - "require": "./dist/cjs/*.js", - "types": "./dist/types/*.d.ts" - } - }, - "typesVersions": { - "*": { - "index.d.ts": [ - "dist/types/index.d.ts" - ], - "*": [ - "dist/types/*" - ] - } - }, - "files": [ - "dist", - "docs", - "CHANGELOG.md", - "LICENSE", - "README.md" + "private": true, + "workspaces": [ + "packages/*" ], - "dependencies": { - "@stablelib/ed25519": "^1.0.2", - "big-integer": "^1.6.51", - "one-webcrypto": "^1.0.3", - "uint8arrays": "^3.0.0" - }, "devDependencies": { - "@types/jest": "^27.4.1", - "@types/node": "^17.0.23", - "@typescript-eslint/eslint-plugin": "^5.18.0", - "@typescript-eslint/parser": "^5.18.0", - "copyfiles": "^2.4.1", - "eslint": "^8.12.0", - "fast-check": "^2.24.0", - "jest": "^27.5.1", - "rimraf": "^3.0.2", - "ts-jest": "^27.1.4", - "typescript": "^4.6.3", - "yarn": "^1.22.18" + "ts-node": "^10.8.2" } } diff --git a/packages/core/jest.config.ts b/packages/core/jest.config.ts new file mode 100644 index 0000000..66af5b0 --- /dev/null +++ b/packages/core/jest.config.ts @@ -0,0 +1,3 @@ +import baseConfig from "../../jest.config" + +export default baseConfig diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 0000000..9b53967 --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,84 @@ +{ + "name": "@ucans/core", + "version": "0.11.0", + "description": "Core UCAN implementation", + "author": "Daniel Holmgren ", + "repository": { + "type": "git", + "url": "https://github.com/ucan-wg/ts-ucan" + }, + "homepage": "https://guide.fission.codes", + "license": "Apache-2.0", + "engines": { + "node": ">=15" + }, + "scripts": { + "prebuild": "rimraf dist", + "build": "yarn run dist", + "dev": "tsc --watch --module commonjs --outDir ./dist/cjs/ --sourceMap", + "dist": "yarn run dist:prep && yarn run dist:src && yarn run dist:cjs && yarn run dist:esm && yarn run dist:types && yarn run dist:pkg", + "dist:cjs": "tsc --project ./dist/ --module commonjs --outDir ./dist/cjs/ --sourceMap", + "dist:esm": "tsc --project ./dist/ --module es2020 --outDir ./dist/esm/ --sourceMap", + "dist:pkg": "node ../../scripts/package.js", + "dist:prep": "copyfiles --error tsconfig.json ./dist/", + "dist:src": "copyfiles --error --up 1 \"./src/**/*\" ./dist/src/", + "dist:types": "tsc --project ./dist/ --emitDeclarationOnly --declaration --declarationDir ./dist/types/", + "lint": "eslint src/**/*.ts src/*.ts tests/**/*.ts tests/*.ts", + "prepare": "yarn build", + "publish-alpha": "yarn publish --tag alpha --access public", + "publish-stable": "yarn publish --tag latest --access public", + "test": "jest", + "test:watch": "jest --watch" + }, + "exports": { + ".": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js", + "types": "./dist/types/index.d.ts" + }, + "./*.js": { + "import": "./dist/esm/*.js", + "require": "./dist/cjs/*.js", + "types": "./dist/types/*.d.ts" + }, + "./*": { + "import": "./dist/esm/*.js", + "require": "./dist/cjs/*.js", + "types": "./dist/types/*.d.ts" + } + }, + "typesVersions": { + "*": { + "index.d.ts": [ + "dist/types/index.d.ts" + ], + "*": [ + "dist/types/*" + ] + } + }, + "files": [ + "dist", + "docs", + "CHANGELOG.md", + "LICENSE", + "README.md" + ], + "dependencies": { + "uint8arrays": "^3.0.0" + }, + "devDependencies": { + "@types/jest": "^27.4.1", + "@types/node": "^17.0.23", + "@typescript-eslint/eslint-plugin": "^5.18.0", + "@typescript-eslint/parser": "^5.18.0", + "copyfiles": "^2.4.1", + "eslint": "^8.12.0", + "fast-check": "^2.24.0", + "jest": "^27.5.1", + "rimraf": "^3.0.2", + "ts-jest": "^27.1.4", + "typescript": "^4.6.3", + "yarn": "^1.22.18" + } +} diff --git a/src/attenuation.ts b/packages/core/src/attenuation.ts similarity index 89% rename from src/attenuation.ts rename to packages/core/src/attenuation.ts index 26ee68b..85c570b 100644 --- a/src/attenuation.ts +++ b/packages/core/src/attenuation.ts @@ -1,4 +1,5 @@ import * as token from "./token.js" +import Plugins from "./plugins.js" import { Capability } from "./capability/index.js" import { Ucan } from "./types.js" import { ResourcePointer } from "./capability/resource-pointer.js" @@ -119,11 +120,12 @@ export type OwnershipScope * out different ways of delegating a capability from the attenuations. * It also makes it possible to return early if a valid delegation chain has been found. */ -export async function* delegationChains( - semantics: DelegationSemantics, - ucan: Ucan, - isRevoked: (ucan: Ucan) => Promise = async () => false -): AsyncIterable { +export const delegationChains = (plugins: Plugins) => + async function* ( + semantics: DelegationSemantics, + ucan: Ucan, + isRevoked: (ucan: Ucan) => Promise = async () => false, + ): AsyncIterable { if (await isRevoked(ucan)) { yield new Error(`UCAN Revoked: ${token.encode(ucan)}`) @@ -131,7 +133,7 @@ export async function* delegationChains( } yield* capabilitiesFromParenthood(ucan) - yield* capabilitiesFromDelegation(semantics, ucan, isRevoked) + yield* capabilitiesFromDelegation(plugins, semantics, ucan, isRevoked) } @@ -265,14 +267,15 @@ function* capabilitiesFromParenthood(ucan: Ucan): Iterable { async function* capabilitiesFromDelegation( + plugins: Plugins, semantics: DelegationSemantics, ucan: Ucan, - isRevoked: (ucan: Ucan) => Promise + isRevoked: (ucan: Ucan) => Promise, ): AsyncIterable { let proofIndex = 0 - for await (const proof of token.validateProofs(ucan)) { + for await (const proof of token.validateProofs(plugins)(ucan)) { if (proof instanceof Error) { yield proof continue @@ -283,15 +286,15 @@ async function* capabilitiesFromDelegation( switch (capability.with.scheme.toLowerCase()) { case "my": continue // cannot be delegated, only introduced by parenthood. case "as": { - yield* handleAsDelegation(semantics, capability, ucan, proof, isRevoked) + yield* handleAsDelegation(plugins, semantics, capability, ucan, proof, isRevoked) break } case "prf": { - yield* handlePrfDelegation(semantics, capability, ucan, proof, proofIndex, isRevoked) + yield* handlePrfDelegation(plugins, semantics, capability, ucan, proof, proofIndex, isRevoked) break } default: { - yield* handleNormalDelegation(semantics, capability, ucan, proof, isRevoked) + yield* handleNormalDelegation(plugins, semantics, capability, ucan, proof, isRevoked) } } } catch (e) { @@ -313,11 +316,12 @@ async function* capabilitiesFromDelegation( async function* handleAsDelegation( + plugins: Plugins, semantics: DelegationSemantics, capability: Capability, ucan: Ucan, proof: Ucan, - isRevoked: (ucan: Ucan) => Promise + isRevoked: (ucan: Ucan) => Promise, ): AsyncIterable { const split = capability.with.hierPart.split(":") const scheme = split[ split.length - 1 ] @@ -326,7 +330,7 @@ async function* handleAsDelegation( ? SUPERUSER : { scheme, ability: capability.can } - for await (const delegationChain of delegationChains(semantics, proof, isRevoked)) { + for await (const delegationChain of delegationChains(plugins)(semantics, proof, isRevoked)) { if (delegationChain instanceof Error) { yield delegationChain continue @@ -352,12 +356,13 @@ async function* handleAsDelegation( async function* handlePrfDelegation( + plugins: Plugins, semantics: DelegationSemantics, capability: Capability, ucan: Ucan, proof: Ucan, proofIndex: number, - isRevoked: (ucan: Ucan) => Promise + isRevoked: (ucan: Ucan) => Promise, ): AsyncIterable { if ( capability.with.hierPart !== SUPERUSER @@ -367,7 +372,7 @@ async function* handlePrfDelegation( // we only process the delegation if proofIndex === 2 return } - for await (const delegationChain of delegationChains(semantics, proof, isRevoked)) { + for await (const delegationChain of delegationChains(plugins)(semantics, proof, isRevoked)) { if (delegationChain instanceof Error) { yield delegationChain continue @@ -385,13 +390,14 @@ async function* handlePrfDelegation( async function* handleNormalDelegation( + plugins: Plugins, semantics: DelegationSemantics, capability: Capability, ucan: Ucan, proof: Ucan, - isRevoked: (ucan: Ucan) => Promise + isRevoked: (ucan: Ucan) => Promise, ): AsyncIterable { - for await (const delegationChain of delegationChains(semantics, proof, isRevoked)) { + for await (const delegationChain of delegationChains(plugins)(semantics, proof, isRevoked)) { if (delegationChain instanceof Error) { yield delegationChain continue diff --git a/packages/core/src/builder.ts b/packages/core/src/builder.ts new file mode 100644 index 0000000..0b121b3 --- /dev/null +++ b/packages/core/src/builder.ts @@ -0,0 +1,281 @@ +import * as token from "./token.js" +import * as util from "./util.js" +import Plugins from "./plugins.js" + +import { Fact, UcanPayload, isKeypair, Ucan, DidableKey, StoreI, BuilderI, BuildableState, CapabilityLookupCapableState, DefaultableState } from "./types.js" +import { Capability, isCapability } from "./capability/index.js" +import { capabilityCanBeDelegated, DelegationSemantics, DelegationChain } from "./attenuation.js" + + + +function isBuildableState(obj: unknown): obj is BuildableState { + return util.isRecord(obj) + && util.hasProp(obj, "issuer") && isKeypair(obj.issuer) + && util.hasProp(obj, "audience") && typeof obj.audience === "string" + && util.hasProp(obj, "expiration") && typeof obj.expiration === "number" +} + +function isCapabilityLookupCapableState(obj: unknown): obj is CapabilityLookupCapableState { + return util.isRecord(obj) + && util.hasProp(obj, "issuer") && isKeypair(obj.issuer) + && util.hasProp(obj, "expiration") && typeof obj.expiration === "number" +} + +// type BuilderConstructor = new >(state: State, defaultable: DefaultableState) => BuilderI +type BuilderConstructor = { + new >(state: State, defaultable: DefaultableState): BuilderI + create(): BuilderI> +} + +/** + * A builder API for UCANs. + * + * Supports grabbing UCANs from a UCAN `Store` for proofs (see `delegateCapability`). + * + * Example usage: + * + * ```ts + * const ucan = await Builder.create() + * .issuedBy(aliceKeypair) + * .toAudience(bobDID) + * .withLifetimeInSeconds(30) + * .claimCapability({ email: "my@email.com", cap: "SEND" }) + * .delegateCapability(emailSemantics, { email: "my-friends@email.com", cap: "SEND" }, proof) + * .build() + * ``` + */ +const mkBuilderClass = (plugins: Plugins): BuilderConstructor => { + + return class Builder> implements BuilderI { + + private state: State // portion of the state that's required to be set before building + private defaultable: DefaultableState // portion of the state that has sensible defaults + + constructor(state: State, defaultable: DefaultableState) { + this.state = state + this.defaultable = defaultable + } + + /** + * Create an empty builder. + * Before finalising the builder, you need to at least call + * - `issuedBy` + * - `toAudience` and + * - `withLifetimeInSeconds` or `withExpiration`. + * To finalise the builder, call its `build` or `buildPayload` method. + */ + static create(): Builder> { + return new Builder({}, { capabilities: [], facts: [], proofs: [], addNonce: false }) + } + + /** + * @param issuer The issuer as a DID string ("did:key:..."). + * + * The UCAN must be signed with the private key of the issuer to be valid. + */ + issuedBy(issuer: DidableKey): Builder { + if (!isKeypair(issuer)) { + throw new TypeError(`Expected a Keypair, but got ${issuer}`) + } + return new Builder({ ...this.state, issuer }, this.defaultable) + } + + /** + * @param audience The audience as a DID string ("did:key:..."). + * + * This is the identity this UCAN transfers rights to. + * It could e.g. be the DID of a service you're posting this UCAN as a JWT to, + * or it could be the DID of something that'll use this UCAN as a proof to + * continue the UCAN chain as an issuer. + */ + toAudience(audience: string): Builder { + if (typeof audience !== "string") { + throw new TypeError(`Expected audience DID as string, but got ${audience}`) + } + return new Builder({ ...this.state, audience }, this.defaultable) + } + + /** + * @param seconds The number of seconds from the calltime of this function + * to set the expiry timestamp to. + */ + withLifetimeInSeconds(seconds: number): Builder { + if (typeof seconds !== "number") { + throw new TypeError(`Expected seconds as number, but got ${seconds}`) + } + if (!isFinite(seconds) || seconds <= 0) { + throw new TypeError(`Expected seconds to be a positive number, but got ${seconds}`) + } + return this.withExpiration(Math.floor(Date.now() / 1000) + seconds) + } + + /** + * @param expiration The UTCTime timestamp (in seconds) for when the UCAN should expire. + */ + withExpiration(expiration: number): Builder { + if (typeof expiration !== "number" || !isFinite(expiration)) { + throw new TypeError(`Expected expiration as number, but got ${expiration}`) + } + if (this.defaultable.notBefore != null && expiration < this.defaultable.notBefore) { + throw new Error(`Can't set expiration to ${expiration} which is before 'notBefore': ${this.defaultable.notBefore}`) + } + return new Builder({ ...this.state, expiration }, this.defaultable) + } + + /** + * @param notBeforeTimestamp The UTCTime timestamp (in seconds) of when the UCAN becomes active. + */ + withNotBefore(notBeforeTimestamp: number): Builder { + if (typeof notBeforeTimestamp !== "number" || !isFinite(notBeforeTimestamp)) { + throw new TypeError(`Expected notBeforeTimestamp as number, but got ${notBeforeTimestamp}`) + } + if (util.hasProp(this.state, "expiration") && typeof this.state.expiration === "number" && this.state.expiration < notBeforeTimestamp) { + throw new Error(`Can't set 'notBefore' to ${notBeforeTimestamp} which is after expiration: ${this.state.expiration}`) + } + return new Builder(this.state, { ...this.defaultable, notBefore: notBeforeTimestamp }) + } + + /** + * @param fact Any fact or proof of knowledge in this UCAN as a record. + * @param facts Arbitrary more facts or proofs of knowledge. + */ + withFact(fact: Fact): Builder + withFact(fact: Fact, ...facts: Fact[]): Builder + withFact(fact: Fact, ...facts: Fact[]): Builder { + if (!util.isRecord(fact) || facts.some(fct => !util.isRecord(fct))) { + throw new TypeError(`Expected fact(s) to be a record, but got ${fact}`) + } + return new Builder(this.state, { + ...this.defaultable, + facts: [ ...this.defaultable.facts, fact, ...facts ] + }) + } + + /** + * Will ensure that the built UCAN includes a number used once. + */ + withNonce(): Builder { + return new Builder(this.state, { ...this.defaultable, addNonce: true }) + } + + /** + * Claim capabilities 'by parenthood'. + */ + claimCapability(capability: Capability): Builder + claimCapability(capability: Capability, ...capabilities: Capability[]): Builder + claimCapability(capability: Capability, ...capabilities: Capability[]): Builder { + if (!isCapability(capability)) { + throw new TypeError(`Expected capability, but got ${JSON.stringify(capability, null, " ")}`) + } + return new Builder(this.state, { + ...this.defaultable, + capabilities: [ ...this.defaultable.capabilities, capability, ...capabilities ] + }) + } + + /** + * Delegate capabilities from a given proof to the audience of the UCAN you're building. + * + * @param semantics The rules for which delegations of capabilities are allowed. + * @param requiredCapability The capability you want to delegate. + * + * Then, one of + * @param proof The proof chain that grants the issuer of this UCAN at least the capabilities you want to delegate, or + * @param store The UCAN store in which to try to find a UCAN granting you enough capabilities to delegate given capabilities. + * + * @throws If given store can't provide a UCAN for delegating given capability + * @throws If given proof can't be used to delegate given capability + * @throws If the builder hasn't set an issuer and expiration yet + */ + delegateCapability(requiredCapability: Capability, store: StoreI): State extends CapabilityLookupCapableState ? Builder : never + delegateCapability(requiredCapability: Capability, proof: DelegationChain, semantics: DelegationSemantics): State extends CapabilityLookupCapableState ? Builder : never + delegateCapability(requiredCapability: Capability, storeOrProof: StoreI | DelegationChain, semantics?: DelegationSemantics): Builder { + if (!isCapability(requiredCapability)) { + throw new TypeError(`Expected 'requiredCapability' as a second argument, but got ${requiredCapability}`) + } + if (!isCapabilityLookupCapableState(this.state)) { + throw new Error(`Can't delegate capabilities without having these paramenters set in the builder: issuer and expiration.`) + } + + function isProof(proof: StoreI | DelegationChain): proof is DelegationChain { + return util.hasProp(proof, "capability") || util.hasProp(proof, "ownershipDID") + } + + if (isProof(storeOrProof)) { + if (semantics == null) { + throw new TypeError(`Expected 'semantics' as third argument if a 'proof' DelegationChain was passed as second.`) + } + const proof: DelegationChain = storeOrProof + const ucan = proof.ucan + if (!capabilityCanBeDelegated(semantics, requiredCapability, proof)) { + throw new Error(`Can't add capability to UCAN: Given proof doesn't give required rights to delegate.`) + } + return new Builder(this.state, { + ...this.defaultable, + capabilities: [ ...this.defaultable.capabilities, requiredCapability ], + proofs: this.defaultable.proofs.find(p => token.encode(p) === token.encode(ucan)) == null + ? [ ...this.defaultable.proofs, ucan ] + : this.defaultable.proofs + }) + } else { + const store: StoreI = storeOrProof + const issuer = this.state.issuer.did() + // we look up a proof that has our issuer as an audience + const result = util.first(store.findWithCapability(issuer, requiredCapability, issuer)) + if (result != null) { + const ucan = result.ucan + const ucanEncoded = token.encode(ucan) + return new Builder(this.state, { + ...this.defaultable, + capabilities: [ ...this.defaultable.capabilities, requiredCapability ], + proofs: this.defaultable.proofs.find(proof => token.encode(proof) === ucanEncoded) == null + ? [ ...this.defaultable.proofs, ucan ] + : this.defaultable.proofs + }) + } else { + throw new Error(`Couldn't add capability to UCAN. Couldn't find anything providing this capability in given store.`) + } + } + } + + /** + * Build the UCAN body. This can be used if you want to sign the UCAN yourself afterwards. + */ + buildPayload(): State extends BuildableState ? UcanPayload : never + buildPayload(): UcanPayload { + if (!isBuildableState(this.state)) { + throw new Error(`Builder is missing one of the required properties before it can be built: issuer, audience and expiration.`) + } + return token.buildPayload({ + issuer: this.state.issuer.did(), + audience: this.state.audience, + + expiration: this.state.expiration, + notBefore: this.defaultable.notBefore, + addNonce: this.defaultable.addNonce, + + capabilities: this.defaultable.capabilities, + facts: this.defaultable.facts, + proofs: this.defaultable.proofs.map(proof => token.encode(proof)), + }) + } + + /** + * Finalize: Build and sign the UCAN. + * + * @throws If the builder hasn't yet been set an issuer, audience and expiration. + */ + async build(): Promise + async build(): Promise { + if (!isBuildableState(this.state)) { + throw new Error(`Builder is missing one of the required properties before it can be built: issuer, audience and expiration.`) + } + const payload = this.buildPayload() + return await token.signWithKeypair(plugins)(payload, this.state.issuer) + } + + } + +} + +export default mkBuilderClass \ No newline at end of file diff --git a/src/capability/ability.ts b/packages/core/src/capability/ability.ts similarity index 97% rename from src/capability/ability.ts rename to packages/core/src/capability/ability.ts index 873c5b4..b3c8b70 100644 --- a/src/capability/ability.ts +++ b/packages/core/src/capability/ability.ts @@ -1,6 +1,11 @@ import { Superuser, SUPERUSER } from "./super-user.js" import * as util from "../util.js" +// RE-EXPORTS + + +export { Superuser, SUPERUSER } + // 💎 diff --git a/src/capability/index.ts b/packages/core/src/capability/index.ts similarity index 92% rename from src/capability/index.ts rename to packages/core/src/capability/index.ts index 148306d..b315878 100644 --- a/src/capability/index.ts +++ b/packages/core/src/capability/index.ts @@ -1,17 +1,16 @@ import * as ability from "./ability.js" import * as resourcePointer from "./resource-pointer.js" -import * as superUser from "./super-user.js" import * as util from "../util.js" import { Ability, isAbility } from "./ability.js" import { ResourcePointer, isResourcePointer } from "./resource-pointer.js" -import { Superuser, SUPERUSER } from "./super-user.js" +import { Superuser } from "./super-user.js" // RE-EXPORTS -export { ability, resourcePointer, superUser } +export { ability, resourcePointer, Ability, isAbility } @@ -53,7 +52,7 @@ export function isEncodedCapability(obj: unknown): obj is EncodedCapability { export function as(did: string, resource: Superuser | string): Capability { return { with: resourcePointer.as(did, resource), - can: SUPERUSER + can: ability.SUPERUSER } } @@ -61,7 +60,7 @@ export function as(did: string, resource: Superuser | string): Capability { export function my(resource: Superuser | string): Capability { return { with: resourcePointer.my(resource), - can: SUPERUSER + can: ability.SUPERUSER } } diff --git a/src/capability/resource-pointer.ts b/packages/core/src/capability/resource-pointer.ts similarity index 100% rename from src/capability/resource-pointer.ts rename to packages/core/src/capability/resource-pointer.ts diff --git a/src/capability/super-user.ts b/packages/core/src/capability/super-user.ts similarity index 100% rename from src/capability/super-user.ts rename to packages/core/src/capability/super-user.ts diff --git a/src/compatibility.ts b/packages/core/src/compatibility.ts similarity index 100% rename from src/compatibility.ts rename to packages/core/src/compatibility.ts diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 0000000..694e36e --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,46 @@ +import Plugins from "./plugins.js" +import * as token from "./token.js" +import * as verifyLib from "./verify.js" +import * as attenuation from "./attenuation.js" +import mkBuilderClass from "./builder.js" +import mkStoreClass from "./store.js" + +export * from "./attenuation.js" +export * from "./builder.js" +export * from "./store.js" +export * from "./token.js" +export * from "./types.js" +export * from "./verify.js" +export * from "./plugins.js" +export * from "./util.js" + +export * as capability from "./capability/index.js" +export * as ability from "./capability/ability.js" + +export { ResourcePointer, isResourcePointer } from "./capability/resource-pointer.js" +export { Ability, isAbility, Superuser, SUPERUSER } from "./capability/ability.js" +export { Capability, EncodedCapability, isCapability } from "./capability/index.js" + +export const getPluginInjectedApi = (plugins: Plugins) => { + const build = token.build(plugins) + const sign = token.sign(plugins) + const signWithKeypair = token.signWithKeypair(plugins) + const validate = token.validate(plugins) + const validateProofs = token.validateProofs(plugins) + const verify = verifyLib.verify(plugins) + const delegationChains = attenuation.delegationChains(plugins) + const Builder = mkBuilderClass(plugins) + const Store = mkStoreClass(plugins) + + return { + build, + sign, + signWithKeypair, + validate, + validateProofs, + verify, + delegationChains, + Builder, + Store + } +} \ No newline at end of file diff --git a/packages/core/src/plugins.ts b/packages/core/src/plugins.ts new file mode 100644 index 0000000..e8de469 --- /dev/null +++ b/packages/core/src/plugins.ts @@ -0,0 +1,90 @@ +import * as uint8arrays from "uint8arrays" + +export type DidKeyPlugin = { + prefix: Uint8Array + jwtAlg: string + verifySignature: (did: string, data: Uint8Array, sig: Uint8Array) => Promise +} + +export type DidMethodPlugin = { + checkJwtAlg: (did: string, jwtAlg: string) => boolean + verifySignature: (did: string, data: Uint8Array, sig: Uint8Array) => Promise +} + +export class Plugins { + + constructor( + public keys: DidKeyPlugin[], + public methods: Record + ) {} + + verifyIssuerAlg(did: string, jwtAlg: string): boolean { + const didMethod = parseDidMethod(did) + if(didMethod === "key") { + const bytes = parsePrefixedBytes(did) + for (const keyPlugin of this.keys) { + if(hasPrefix(bytes, keyPlugin.prefix)) { + return jwtAlg === keyPlugin.jwtAlg + } + } + } else { + const maybePlugin = this.methods[didMethod] + if(maybePlugin) { + return maybePlugin.checkJwtAlg(did, jwtAlg) + } + } + throw new Error(`DID method not supported by plugins: ${did}`) + } + + async verifySignature(did: string, data: Uint8Array, sig: Uint8Array): Promise { + const didMethod = parseDidMethod(did) + if(didMethod === "key") { + const bytes = parsePrefixedBytes(did) + for (const keyPlugin of this.keys) { + if(hasPrefix(bytes, keyPlugin.prefix)) { + return keyPlugin.verifySignature(did, data, sig) + } + } + } else { + const maybePlugin = this.methods[didMethod] + if (maybePlugin) { + return maybePlugin.verifySignature(did, data, sig) + } + } + throw new Error(`DID method not supported by plugins: ${did}`) + } +} + +export default Plugins + +const hasPrefix = ( + prefixedKey: Uint8Array, + prefix: Uint8Array +): boolean => { + return uint8arrays.equals(prefix, prefixedKey.subarray(0, prefix.byteLength)) +} + +const BASE58_DID_PREFIX = "did:key:z" + +// @TODO would be better to follow the actual varint spec here (instead of guess & check): +// https://github.com/multiformats/unsigned-varint +const parsePrefixedBytes = (did: string): Uint8Array => { + if(!did.startsWith(BASE58_DID_PREFIX)) { + throw new Error(`Not a valid base58 formatted did:key: ${did}`) + } + return uint8arrays.fromString( + did.slice(BASE58_DID_PREFIX.length), + "base58btc" + ) +} + +const parseDidMethod = (did: string) => { + const parts = did.split(":") + if(parts[0] !== "did") { + throw new Error(`Not a DID: ${did}`) + } + if(parts[1].length < 1) { + throw new Error(`No DID method included: ${did}`) + } + return parts[1] +} \ No newline at end of file diff --git a/src/semver.ts b/packages/core/src/semver.ts similarity index 100% rename from src/semver.ts rename to packages/core/src/semver.ts diff --git a/packages/core/src/store.ts b/packages/core/src/store.ts new file mode 100644 index 0000000..1d62170 --- /dev/null +++ b/packages/core/src/store.ts @@ -0,0 +1,102 @@ +import * as token from "./token.js" +import Plugins from "./plugins.js" +import { capabilityCanBeDelegated, DelegationSemantics, DelegationChain, delegationChains, rootIssuer } from "./attenuation.js" +import { IndexByAudience, StoreI, Ucan } from "./types.js" +import { Capability } from "./capability/index.js" + +type StoreConstructor = { + new (knownSemantics: DelegationSemantics, index: IndexByAudience): StoreI + empty(knownSemantics: DelegationSemantics): StoreI + fromTokens(knownSemantics: DelegationSemantics, tokens: Iterable | AsyncIterable): Promise +} + +const mkStoreClass = (plugins: Plugins): StoreConstructor => { + return class Store implements StoreI{ + + private index: IndexByAudience + private knownSemantics: DelegationSemantics + + constructor(knownSemantics: DelegationSemantics, index: IndexByAudience) { + this.index = index + this.knownSemantics = knownSemantics + } + + static empty(knownSemantics: DelegationSemantics): Store { + return new Store(knownSemantics, {}) + } + + static async fromTokens( + knownSemantics: DelegationSemantics, + tokens: Iterable | AsyncIterable, + ): Promise { + const store = Store.empty(knownSemantics) + for await (const encodedUcan of tokens) { + const ucan = await token.validate(plugins)(encodedUcan) + await store.add(ucan) + } + return store + } + + async add(ucan: Ucan): Promise { + const audience = ucan.payload.aud + const byAudience = this.index[ audience ] ?? [] + const encoded = token.encode(ucan) + + if (byAudience.find(stored => token.encode(stored.processedUcan) === encoded) != null) { + return + } + + const chains = [] + for await (const delegationChain of delegationChains(plugins)(this.knownSemantics, ucan)) { + if (delegationChain instanceof Error) { + console.warn(`Delegation chain error while storing UCAN:`, delegationChain) + continue + } + chains.push(delegationChain) + } + + // Also do this *after* the all awaits to prevent races. + if (byAudience.find(stored => token.encode(stored.processedUcan) === encoded) != null) { + return + } + + byAudience.push({ + processedUcan: ucan, + capabilities: chains + }) + this.index[ audience ] = byAudience + } + + getByAudience(audience: string): Ucan[] { + return (this.index[ audience ] ?? []).map(elem => elem.processedUcan) + } + + findByAudience(audience: string, predicate: (ucan: Ucan) => boolean): Ucan | null { + return this.index[ audience ]?.find(elem => predicate(elem.processedUcan))?.processedUcan ?? null + } + + *findWithCapability( + audience: string, + requiredCapability: Capability, + requiredIssuer: string, + ): Iterable { + const cache = this.index[ audience ] + + if (cache == null) { + return + } + + for (const cacheElement of cache) { + for (const delegationChain of cacheElement.capabilities) { + if (capabilityCanBeDelegated(this.knownSemantics, requiredCapability, delegationChain) + && rootIssuer(delegationChain) === requiredIssuer) { + yield delegationChain + } + } + } + } + + } +} + +export default mkStoreClass \ No newline at end of file diff --git a/src/token.ts b/packages/core/src/token.ts similarity index 80% rename from src/token.ts rename to packages/core/src/token.ts index 787c8f1..b5420ca 100644 --- a/src/token.ts +++ b/packages/core/src/token.ts @@ -1,15 +1,14 @@ -import * as uint8arrays from "uint8arrays" +import * as uint8arrays from "uint8arrays" // @IMPORT import * as semver from "./semver.js" import * as capability from "./capability/index.js" -import * as did from "./did.js" import * as util from "./util.js" +import Plugins from "./plugins.js" import { Capability, isCapability, isEncodedCapability } from "./capability/index.js" -import { Fact, KeyType, Keypair } from "./types.js" +import { Fact, Keypair, DidableKey } from "./types.js" import { Ucan, UcanHeader, UcanParts, UcanPayload } from "./types.js" import { handleCompatibility } from "./compatibility.js" -import { verifySignatureUtf8 } from "./did/validation.js" // CONSTANTS @@ -44,28 +43,28 @@ const VERSION = { major: 0, minor: 8, patch: 1 } * `prf`, Proofs, nested tokens with equal or greater privileges. * */ -export async function build(params: { - // from/to - issuer: Keypair - audience: string - - // capabilities - capabilities?: Array - - // time bounds - lifetimeInSeconds?: number // expiration overrides lifetimeInSeconds - expiration?: number - notBefore?: number - - // proofs / other info - facts?: Array - proofs?: Array - addNonce?: boolean -}): Promise { +export const build = (plugins: Plugins) => + ( params: { + // from/to + issuer: DidableKey + audience: string + + // capabilities + capabilities?: Array + + // time bounds + lifetimeInSeconds?: number // expiration overrides lifetimeInSeconds + expiration?: number + notBefore?: number + + // proofs / other info + facts?: Array + proofs?: Array + addNonce?: boolean + }): Promise => { const keypair = params.issuer - const didStr = did.publicKeyBytesToDid(keypair.publicKey, keypair.keyType) - const payload = buildPayload({ ...params, issuer: didStr }) - return signWithKeypair(payload, keypair) + const payload = buildPayload({ ...params, issuer: keypair.did() }) + return signWithKeypair(plugins)(payload, keypair) } /** @@ -125,19 +124,19 @@ export function buildPayload(params: { /** * Encloses a UCAN payload as to form a finalised UCAN. */ -export async function sign( - payload: UcanPayload, - keyType: KeyType, - signFn: (data: Uint8Array) => Promise -): Promise { +export const sign = (plugins: Plugins) => + async (payload: UcanPayload, + jwtAlg: string, + signFn: (data: Uint8Array) => Promise, + ): Promise => { const header: UcanHeader = { - alg: jwtAlgorithm(keyType), + alg: jwtAlg, typ: TYPE, ucv: VERSION, } // Issuer key type must match UCAN algorithm - if (did.didToPublicKey(payload.iss).type !== keyType) { + if (!plugins.verifyIssuerAlg(payload.iss, jwtAlg)) { throw new Error("The issuer's key type must match the given key type.") } @@ -164,14 +163,14 @@ export async function sign( /** * `sign` with a `Keypair`. */ -export async function signWithKeypair( - payload: UcanPayload, - keypair: Keypair -): Promise { - return sign( +export const signWithKeypair = (plugins: Plugins) => + ( payload: UcanPayload, + keypair: Keypair, + ): Promise => { + return sign(plugins)( payload, - keypair.keyType, - data => keypair.sign(data) + keypair.jwtAlg, + data => keypair.sign(data), ) } @@ -298,15 +297,14 @@ export function parse(encodedUcan: string): UcanParts { // VALIDATION - /** * Validation options */ export interface ValidateOptions { checkIssuer?: boolean + checkSignature?: boolean checkIsExpired?: boolean checkIsTooEarly?: boolean - checkSignature?: boolean } /** @@ -320,24 +318,25 @@ export interface ValidateOptions { * @returns the parsed & validated UCAN (one layer) * @throws Error if the UCAN is invalid */ -export async function validate(encodedUcan: string, options?: ValidateOptions): Promise { - const checkIssuer = options?.checkIssuer ?? true - const checkIsExpired = options?.checkIsExpired ?? true - const checkIsTooEarly = options?.checkIsTooEarly ?? true - const checkSignature = options?.checkSignature ?? true +export const validate = (plugins: Plugins) => + async (encodedUcan: string, opts?: Partial): Promise => { + const { checkIssuer = true, checkSignature = true, checkIsExpired = true, checkIsTooEarly = true } = opts ?? {} const { header, payload } = parse(encodedUcan) const [ encodedHeader, encodedPayload, signature ] = encodedUcan.split(".") if (checkIssuer) { - const issuerKeyType = did.didToPublicKey(payload.iss).type - if (jwtAlgorithm(issuerKeyType) !== header.alg) { + const validIssuer = plugins.verifyIssuerAlg(payload.iss, header.alg) + if (!validIssuer) { throw new Error(`Invalid UCAN: ${encodedUcan}: Issuer key type does not match UCAN's \`alg\` property.`) } } if (checkSignature) { - if (!await verifySignatureUtf8(`${encodedHeader}.${encodedPayload}`, signature, payload.iss)) { + const sigBytes = uint8arrays.fromString(signature, "base64url") + const data = uint8arrays.fromString(`${encodedHeader}.${encodedPayload}`, "utf8") + const validSig = await plugins.verifySignature(payload.iss, data, sigBytes) + if (!validSig) { throw new Error(`Invalid UCAN: ${encodedUcan}: Signature invalid.`) } } @@ -359,7 +358,7 @@ export async function validate(encodedUcan: string, options?: ValidateOptions): /** * Proof validation options. */ -export interface ValidateProofsOptions { +export interface ValidateProofsOptions extends ValidateOptions { /** * Whether to check if the ucan's issuer matches its proofs audiences. */ @@ -385,17 +384,16 @@ export interface ValidateProofsOptions { * @return an async iterator of the given ucan's proofs parsed & validated, or an `Error` * for each proof that couldn't be validated or parsed. */ -export async function* validateProofs( - ucan: Ucan, - options?: ValidateOptions & ValidateProofsOptions -): AsyncIterable { - const checkAddressing = options?.checkAddressing ?? true - const checkTimeBoundsSubset = options?.checkTimeBoundsSubset ?? true - const checkVersionMonotonic = options?.checkVersionMonotonic ?? true + +export const validateProofs = (plugins: Plugins) => + async function* ( ucan: Ucan, + opts?: Partial + ): AsyncIterable { + const { checkAddressing = true, checkTimeBoundsSubset = true, checkVersionMonotonic = true } = opts || {} for (const prf of ucan.payload.prf) { try { - const proof = await validate(prf, options) + const proof = await validate(plugins)(prf, opts) if (checkAddressing && ucan.payload.iss !== proof.payload.aud) { throw new Error(`Invalid Proof: Issuer ${ucan.payload.iss} doesn't match parent's audience ${proof.payload.aud}`) @@ -441,21 +439,4 @@ export function isExpired(ucan: Ucan): boolean { export const isTooEarly = (ucan: Ucan): boolean => { if (ucan.payload.nbf == null) return false return ucan.payload.nbf > Math.floor(Date.now() / 1000) -} - - - -// ㊙️ - - -/** - * JWT algorithm to be used in a JWT header. - */ -function jwtAlgorithm(keyType: KeyType): string { - switch (keyType) { - case "bls12-381": throw new Error(`Unknown KeyType "${keyType}"`) - case "ed25519": return "EdDSA" - case "rsa": return "RS256" - default: throw new Error(`Unknown KeyType "${keyType}"`) - } -} +} \ No newline at end of file diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts new file mode 100644 index 0000000..63044a5 --- /dev/null +++ b/packages/core/src/types.ts @@ -0,0 +1,172 @@ +import * as semver from "./semver.js" +import { SemVer } from "./semver.js" +import { SupportedEncodings } from "uint8arrays/util/bases.js" // @IMPORT +import { Capability, isCapability, isEncodedCapability } from "./capability/index.js" +import * as util from "./util.js" +import { DelegationChain, DelegationSemantics } from "./attenuation.js" + + +// 💎 + + +export type Ucan = { + header: UcanHeader + payload: UcanPayload + // We need to keep the encoded version around to preserve the signature + signedData: string + signature: string +} + + + +// CHUNKS + + +export interface UcanParts { + header: UcanHeader + payload: UcanPayload +} + +export type UcanHeader = { + alg: string + typ: string + ucv: SemVer +} + +export type UcanPayload = { + iss: string + aud: string + exp: number + nbf?: number + nnc?: string + att: Array + fct?: Array + prf: Array +} + + + +// FRAGMENTS + + +export type Fact = Record + + + +// CRYPTOGRAPHY + +export interface Didable { + did: () => string +} + +export interface ExportableKey { + export: (format?: Encodings) => Promise +} + +export interface Keypair { + jwtAlg: string + sign: (msg: Uint8Array) => Promise +} + +export interface DidableKey extends Didable, Keypair {} + +// MISC + + +export type Encodings = SupportedEncodings + + +// STORE + + +export interface IndexByAudience { + [ audienceDID: string ]: Array<{ + processedUcan: Ucan + capabilities: DelegationChain[] + }> +} + +export interface StoreI { + add(ucan: Ucan): Promise + getByAudience(audience: string): Ucan[] + findByAudience(audience: string, predicate: (ucan: Ucan) => boolean): Ucan | null + findWithCapability( + audience: string, + requiredCapability: Capability, + requiredIssuer: string, + ): Iterable +} + +// BUILDER + +export interface BuildableState { + issuer: DidableKey + audience: string + expiration: number +} + + +export interface DefaultableState { + capabilities: Capability[] + facts: Fact[] + proofs: Ucan[] + addNonce: boolean + notBefore?: number +} + +// the state neccessary for being able to lookup fitting capabilities in the UCAN store +export interface CapabilityLookupCapableState { + issuer: Keypair + expiration: number +} + +export interface BuilderI> { + issuedBy(issuer: DidableKey): BuilderI + toAudience(audience: string): BuilderI + withLifetimeInSeconds(seconds: number): BuilderI + withExpiration(expiration: number): BuilderI + withNotBefore(notBeforeTimestamp: number): BuilderI + withFact(fact: Fact): BuilderI + withFact(fact: Fact, ...facts: Fact[]): BuilderI + withFact(fact: Fact, ...facts: Fact[]): BuilderI + withNonce(): BuilderI + claimCapability(capability: Capability): BuilderI + claimCapability(capability: Capability, ...capabilities: Capability[]): BuilderI + claimCapability(capability: Capability, ...capabilities: Capability[]): BuilderI + delegateCapability(requiredCapability: Capability, store: StoreI): State extends CapabilityLookupCapableState ? BuilderI : never + delegateCapability(requiredCapability: Capability, proof: DelegationChain, semantics: DelegationSemantics): State extends CapabilityLookupCapableState ? BuilderI : never + delegateCapability(requiredCapability: Capability, storeOrProof: StoreI | DelegationChain, semantics?: DelegationSemantics): BuilderI + buildPayload(): State extends BuildableState ? UcanPayload : never + buildPayload(): UcanPayload + build(): Promise + build(): Promise +} + + +// TYPE CHECKS + + +export function isKeypair(obj: unknown): obj is Keypair { + return util.isRecord(obj) + && util.hasProp(obj, "jwtAlg") && typeof obj.jwtAlg === "string" + && util.hasProp(obj, "sign") && typeof obj.sign === "function" +} + +export function isUcanHeader(obj: unknown): obj is UcanHeader { + return util.isRecord(obj) + && util.hasProp(obj, "alg") && typeof obj.alg === "string" + && util.hasProp(obj, "typ") && typeof obj.typ === "string" + && util.hasProp(obj, "ucv") && semver.isSemVer(obj.ucv) +} + +export function isUcanPayload(obj: unknown): obj is UcanPayload { + return util.isRecord(obj) + && util.hasProp(obj, "iss") && typeof obj.iss === "string" + && util.hasProp(obj, "aud") && typeof obj.aud === "string" + && util.hasProp(obj, "exp") && typeof obj.exp === "number" + && (!util.hasProp(obj, "nbf") || typeof obj.nbf === "number") + && (!util.hasProp(obj, "nnc") || typeof obj.nnc === "string") + && util.hasProp(obj, "att") && Array.isArray(obj.att) && obj.att.every(a => isCapability(a) || isEncodedCapability(a)) + && (!util.hasProp(obj, "fct") || Array.isArray(obj.fct) && obj.fct.every(util.isRecord)) + && util.hasProp(obj, "prf") && Array.isArray(obj.prf) && obj.prf.every(str => typeof str === "string") +} \ No newline at end of file diff --git a/src/util.ts b/packages/core/src/util.ts similarity index 100% rename from src/util.ts rename to packages/core/src/util.ts diff --git a/src/verify.ts b/packages/core/src/verify.ts similarity index 94% rename from src/verify.ts rename to packages/core/src/verify.ts index e6a5c1e..8797dfc 100644 --- a/src/verify.ts +++ b/packages/core/src/verify.ts @@ -1,4 +1,5 @@ import * as token from "./token.js" +import Plugins from "./plugins.js" import { capabilityCanBeDelegated, DelegationSemantics, DelegationChain, delegationChains, equalCanDelegate, rootIssuer } from "./attenuation.js" import { Capability, isCapability } from "./capability/index.js" import { Fact, Ucan } from "./types.js" @@ -53,7 +54,8 @@ export interface VerifyOptions { * * @throws TypeError if the passed arguments don't match what is expected */ -export async function verify(ucan: string, options: VerifyOptions): Promise> { +export const verify = (plugins: Plugins) => + async (ucan: string, options: VerifyOptions): Promise> => { const { audience, requiredCapabilities } = options const semantics = options.semantics ?? equalCanDelegate const isRevoked = options.isRevoked ?? (async () => false) @@ -86,7 +88,7 @@ export async function verify(ucan: string, options: VerifyOptions): Promise", + "repository": { + "type": "git", + "url": "https://github.com/ucan-wg/ts-ucan" + }, + "homepage": "https://guide.fission.codes", + "license": "Apache-2.0", + "engines": { + "node": ">=15" + }, + "scripts": { + "prebuild": "rimraf dist", + "build": "yarn run dist", + "dev": "tsc --watch --module commonjs --outDir ./dist/cjs/ --sourceMap", + "dist": "yarn run dist:prep && yarn run dist:src && yarn run dist:cjs && yarn run dist:esm && yarn run dist:types && yarn run dist:pkg", + "dist:cjs": "tsc --project ./dist/ --module commonjs --outDir ./dist/cjs/ --sourceMap", + "dist:esm": "tsc --project ./dist/ --module es2020 --outDir ./dist/esm/ --sourceMap", + "dist:pkg": "node ../../scripts/package.js", + "dist:prep": "copyfiles --error tsconfig.json ./dist/", + "dist:src": "copyfiles --error --up 1 \"./src/**/*\" ./dist/src/", + "dist:types": "tsc --project ./dist/ --emitDeclarationOnly --declaration --declarationDir ./dist/types/", + "lint": "eslint src/**/*.ts src/*.ts tests/**/*.ts tests/*.ts", + "prepare": "yarn build", + "publish-alpha": "yarn publish --tag alpha", + "publish-stable": "yarn publish --tag latest", + "test": "jest", + "test:watch": "jest --watch" + }, + "exports": { + ".": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js", + "types": "./dist/types/index.d.ts" + }, + "./*.js": { + "import": "./dist/esm/*.js", + "require": "./dist/cjs/*.js", + "types": "./dist/types/*.d.ts" + }, + "./*": { + "import": "./dist/esm/*.js", + "require": "./dist/cjs/*.js", + "types": "./dist/types/*.d.ts" + } + }, + "typesVersions": { + "*": { + "index.d.ts": [ + "dist/types/index.d.ts" + ], + "*": [ + "dist/types/*" + ] + } + }, + "files": [ + "dist", + "docs", + "CHANGELOG.md", + "LICENSE", + "README.md" + ], + "dependencies": { + "@ucans/core": "*", + "@stablelib/ed25519": "^1.0.2", + "big-integer": "^1.6.51", + "one-webcrypto": "^1.0.3", + "uint8arrays": "^3.0.0" + }, + "devDependencies": { + "@types/jest": "^27.4.1", + "@types/node": "^17.0.23", + "@typescript-eslint/eslint-plugin": "^5.18.0", + "@typescript-eslint/parser": "^5.18.0", + "copyfiles": "^2.4.1", + "eslint": "^8.12.0", + "fast-check": "^2.24.0", + "jest": "^27.5.1", + "rimraf": "^3.0.2", + "ts-jest": "^27.1.4", + "typescript": "^4.6.3", + "yarn": "^1.22.18" + } +} diff --git a/packages/default-plugins/src/default-plugins.ts b/packages/default-plugins/src/default-plugins.ts new file mode 100644 index 0000000..25d6a96 --- /dev/null +++ b/packages/default-plugins/src/default-plugins.ts @@ -0,0 +1,9 @@ +import { Plugins } from "@ucans/core" +import { ed25519Plugin } from "./ed25519/plugin.js" +import { p256Plugin } from "./p256/plugin.js" +import { rsaPlugin, rsaOldPlugin } from "./rsa/plugin.js" + +export const defaults = new Plugins( + [ed25519Plugin, p256Plugin, rsaPlugin, rsaOldPlugin], + {}, +) \ No newline at end of file diff --git a/packages/default-plugins/src/ed25519/crypto.ts b/packages/default-plugins/src/ed25519/crypto.ts new file mode 100644 index 0000000..925dc87 --- /dev/null +++ b/packages/default-plugins/src/ed25519/crypto.ts @@ -0,0 +1,10 @@ +import { EDWARDS_DID_PREFIX } from "../prefixes" +import { didFromKeyBytes, keyBytesFromDid } from "../util" + +export const didToPublicKey = (did: string): Uint8Array => { + return keyBytesFromDid(did, EDWARDS_DID_PREFIX) +} + +export const publicKeyToDid = (pubkey: Uint8Array): string => { + return didFromKeyBytes(pubkey, EDWARDS_DID_PREFIX) +} diff --git a/src/keypair/ed25519.ts b/packages/default-plugins/src/ed25519/keypair.ts similarity index 75% rename from src/keypair/ed25519.ts rename to packages/default-plugins/src/ed25519/keypair.ts index a4c49a7..d217546 100644 --- a/src/keypair/ed25519.ts +++ b/packages/default-plugins/src/ed25519/keypair.ts @@ -1,17 +1,22 @@ -import * as ed25519 from "@stablelib/ed25519" import * as uint8arrays from "uint8arrays" +import * as ed25519 from "@stablelib/ed25519" +import * as crypto from "./crypto.js" + +import { DidableKey, Encodings, ExportableKey } from "@ucans/core" -import BaseKeypair from "./base.js" -import { Encodings } from "../types.js" +export class EdKeypair implements DidableKey, ExportableKey { -export class EdKeypair extends BaseKeypair { + public jwtAlg = "EdDSA" private secretKey: Uint8Array + private publicKey: Uint8Array + private exportable: boolean constructor(secretKey: Uint8Array, publicKey: Uint8Array, exportable: boolean) { - super(publicKey, "ed25519", exportable) this.secretKey = secretKey + this.publicKey = publicKey + this.exportable = exportable } static async create(params?: { @@ -32,6 +37,10 @@ export class EdKeypair extends BaseKeypair { return new EdKeypair(secretKey, publicKey, exportable) } + did(): string { + return crypto.publicKeyToDid(this.publicKey) + } + async sign(msg: Uint8Array): Promise { return ed25519.sign(this.secretKey, msg) } diff --git a/packages/default-plugins/src/ed25519/plugin.ts b/packages/default-plugins/src/ed25519/plugin.ts new file mode 100644 index 0000000..a42b842 --- /dev/null +++ b/packages/default-plugins/src/ed25519/plugin.ts @@ -0,0 +1,14 @@ +import { DidKeyPlugin } from "@ucans/core" +import * as ed25519 from "@stablelib/ed25519" +import * as crypto from "./crypto.js" + +import { EDWARDS_DID_PREFIX } from "../prefixes.js" + +export const ed25519Plugin: DidKeyPlugin = { + prefix: EDWARDS_DID_PREFIX, + jwtAlg: "EdDSA", + verifySignature: async (did: string, data: Uint8Array, sig: Uint8Array) => { + const publicKey = crypto.didToPublicKey(did) + return ed25519.verify(publicKey, data, sig) + } +} \ No newline at end of file diff --git a/packages/default-plugins/src/index.ts b/packages/default-plugins/src/index.ts new file mode 100644 index 0000000..4100423 --- /dev/null +++ b/packages/default-plugins/src/index.ts @@ -0,0 +1,12 @@ +export * from "./ed25519/keypair.js" +export * from "./rsa/keypair.js" +export * from "./p256/keypair.js" + +export * from "./ed25519/plugin.js" +export * from "./rsa/plugin.js" +export * from "./p256/plugin.js" + +export * from "./default-plugins.js" + +export * as rsa from "./rsa/crypto.js" +export * as p256 from "./p256/crypto.js" \ No newline at end of file diff --git a/packages/default-plugins/src/p256/crypto.ts b/packages/default-plugins/src/p256/crypto.ts new file mode 100644 index 0000000..ca02f30 --- /dev/null +++ b/packages/default-plugins/src/p256/crypto.ts @@ -0,0 +1,187 @@ +import bigInt from "big-integer" +import * as uint8arrays from "uint8arrays" +import { webcrypto } from "one-webcrypto" +import { AvailableCryptoKeyPair, PrivateKeyJwk } from "../types.js" +import { didFromKeyBytes, keyBytesFromDid } from "../util.js" +import { P256_DID_PREFIX } from "../prefixes.js" + +export const ALG = "ECDSA" +export const DEFAULT_CURVE = "P-256" +export const DEFAULT_HASH_ALG = "SHA-256" + +export const generateKeypair = async (): Promise => { + return await webcrypto.subtle.generateKey( + { + name: ALG, + namedCurve: DEFAULT_CURVE, + }, + false, + [ "sign", "verify" ] + ) +} + +export const importKeypairJwk = async ( + privKeyJwk: PrivateKeyJwk, + exportable = false +): Promise => { + const privateKey = await webcrypto.subtle.importKey( + "jwk", + privKeyJwk, + { + name: ALG, + namedCurve: DEFAULT_CURVE, + }, + exportable, + ["sign" ] + ) + const { kty, crv, x, y} = privKeyJwk + const pubKeyJwk = { kty, crv, x, y} + const publicKey = await webcrypto.subtle.importKey( + "jwk", + pubKeyJwk, + { + name: ALG, + namedCurve: DEFAULT_CURVE, + }, + true, + [ "verify" ] + ) + return { privateKey, publicKey } +} + +export const exportKey = async (key: CryptoKey): Promise => { + const buf = await webcrypto.subtle.exportKey("raw", key) + return new Uint8Array(buf) +} + +export const importKey = async ( + key: Uint8Array +): Promise => { + return await webcrypto.subtle.importKey( + "raw", + key.buffer, + { name: ALG, namedCurve: DEFAULT_CURVE }, + true, + [ "verify" ] + ) +} + +export const sign = async ( + msg: Uint8Array, + privateKey: CryptoKey +): Promise => { + const buf = await webcrypto.subtle.sign( + { name: ALG, hash: { name: DEFAULT_HASH_ALG } }, + privateKey, + msg.buffer + ) + return new Uint8Array(buf) +} + +export const verify = async ( + pubKey: Uint8Array, + msg: Uint8Array, + sig: Uint8Array +): Promise => { + return await webcrypto.subtle.verify( + { name: ALG, hash: { name: DEFAULT_HASH_ALG } }, + await importKey(pubKey), + sig.buffer, + msg.buffer + ) +} + + +export const didToPublicKey = (did: string): Uint8Array => { + // The multiformats space (used by did:key) specifies that NIST P-256 + // keys should be encoded as the 33-byte compressed public key, + // instead of the 65-byte raw public key + const keyBytes = keyBytesFromDid(did, P256_DID_PREFIX) + return decompressP256Pubkey(keyBytes) +} + +export const publicKeyToDid = (publicKey: Uint8Array): string => { + const compressed = compressP256Pubkey(publicKey) + return didFromKeyBytes(compressed, P256_DID_PREFIX) +} + + + +// PUBLIC KEY COMPRESSION +// ------------------------- + +// Compression & Decompression algos from: +// https://stackoverflow.com/questions/48521840/biginteger-to-a-uint8array-of-bytes + +// Public key compression for NIST P-256 +export const compressP256Pubkey = (pubkeyBytes: Uint8Array): Uint8Array => { + if (pubkeyBytes.length !== 65) { + throw new Error("Expected 65 byte pubkey") + } else if (pubkeyBytes[0] !== 0x04) { + throw new Error("Expected first byte to be 0x04") + } + // first byte is a prefix + const x = pubkeyBytes.slice(1, 33) + const y = pubkeyBytes.slice(33, 65) + const out = new Uint8Array(x.length + 1) + + out[0] = 2 + (y[y.length - 1] & 1) + out.set(x, 1) + + return out +} + +// Public key decompression for NIST P-256 +export const decompressP256Pubkey = (compressed: Uint8Array): Uint8Array => { + if (compressed.length !== 33) { + throw new Error("Expected 33 byte compress pubkey") + } else if (compressed[0] !== 0x02 && compressed[0] !== 0x03) { + throw new Error("Expected first byte to be 0x02 or 0x03") + } + // Consts for P256 curve + const two = bigInt(2) + // 115792089210356248762697446949407573530086143415290314195533631308867097853951 + const prime = two + .pow(256) + .subtract(two.pow(224)) + .add(two.pow(192)) + .add(two.pow(96)) + .subtract(1) + const b = bigInt( + "41058363725152142129326129780047268409114441015993725554835256314039467401291", + ) + + // Pre-computed value, or literal + const pIdent = prime.add(1).divide(4) // 28948022302589062190674361737351893382521535853822578548883407827216774463488 + + // This value must be 2 or 3. 4 indicates an uncompressed key, and anything else is invalid. + const signY = bigInt(compressed[0] - 2) + const x = compressed.slice(1) + const xBig = bigInt(uint8arrays.toString(x, "base10")) + + // y^2 = x^3 - 3x + b + const maybeY = xBig + .pow(3) + .subtract(xBig.multiply(3)) + .add(b) + .modPow(pIdent, prime) + + let yBig + // If the parity matches, we found our root, otherwise it's the other root + if (maybeY.mod(2).equals(signY)) { + yBig = maybeY + } else { + // y = prime - y + yBig = prime.subtract(maybeY) + } + const y = uint8arrays.fromString(yBig.toString(10), "base10") + + // left-pad for smaller than 32 byte y + const offset = 32 - y.length + const yPadded = new Uint8Array(32) + yPadded.set(y, offset) + + // concat coords & prepend P-256 prefix + const publicKey = uint8arrays.concat([[0x04], x, yPadded]) + return publicKey +} diff --git a/src/keypair/ecdsa.ts b/packages/default-plugins/src/p256/keypair.ts similarity index 57% rename from src/keypair/ecdsa.ts rename to packages/default-plugins/src/p256/keypair.ts index 8ae1a72..76b8e2f 100644 --- a/src/keypair/ecdsa.ts +++ b/packages/default-plugins/src/p256/keypair.ts @@ -1,63 +1,69 @@ import { webcrypto } from "one-webcrypto" import * as uint8arrays from "uint8arrays" +import { DidableKey, Encodings, ExportableKey } from "@ucans/core" -import * as ecdsa from "../crypto/ecdsa.js" +import * as crypto from "./crypto.js" import { AvailableCryptoKeyPair, - Encodings, isAvailableCryptoKeyPair, - NamedCurve, PrivateKeyJwk, } from "../types.js" -import BaseKeypair from "./base.js" -export class EcdsaKeypair extends BaseKeypair { + +export class EcdsaKeypair implements DidableKey, ExportableKey { + + public jwtAlg = "ES256" + + private publicKey: Uint8Array private keypair: AvailableCryptoKeyPair + private exportable: boolean constructor( keypair: AvailableCryptoKeyPair, publicKey: Uint8Array, - namedCurve: NamedCurve, exportable: boolean ) { - super(publicKey, ecdsa.toKeyType(namedCurve), exportable) this.keypair = keypair + this.publicKey = publicKey + this.exportable = exportable } static async create(params?: { - namedCurve?: NamedCurve exportable?: boolean }): Promise { - const { namedCurve = "P-256", exportable = false } = params || {} - const keypair = await ecdsa.generateKeypair(namedCurve) + const { exportable = false } = params || {} + const keypair = await crypto.generateKeypair() if (!isAvailableCryptoKeyPair(keypair)) { throw new Error(`Couldn't generate valid keypair`) } - const publicKey = await ecdsa.exportKey(keypair.publicKey) - return new EcdsaKeypair(keypair, publicKey, namedCurve, exportable) + const publicKey = await crypto.exportKey(keypair.publicKey) + return new EcdsaKeypair(keypair, publicKey, exportable) } static async importFromJwk( jwk: PrivateKeyJwk, params?: { - namedCurve?: NamedCurve exportable?: boolean }): Promise { - const { namedCurve = "P-256", exportable = false } = params || {} - const keypair = await ecdsa.importKeypairJwk(jwk, namedCurve, exportable) + const { exportable = false } = params || {} + const keypair = await crypto.importKeypairJwk(jwk, exportable) if (!isAvailableCryptoKeyPair(keypair)) { throw new Error(`Couldn't generate valid keypair`) } - const publicKey = await ecdsa.exportKey(keypair.publicKey) - return new EcdsaKeypair(keypair, publicKey, namedCurve, exportable) - } + const publicKey = await crypto.exportKey(keypair.publicKey) + return new EcdsaKeypair(keypair, publicKey, exportable) + } + + did(): string { + return crypto.publicKeyToDid(this.publicKey) + } async sign(msg: Uint8Array): Promise { - return await ecdsa.sign(msg, this.keypair.privateKey) + return await crypto.sign(msg, this.keypair.privateKey) } async export(format: Encodings = "base64pad"): Promise { diff --git a/packages/default-plugins/src/p256/plugin.ts b/packages/default-plugins/src/p256/plugin.ts new file mode 100644 index 0000000..bbf449f --- /dev/null +++ b/packages/default-plugins/src/p256/plugin.ts @@ -0,0 +1,12 @@ +import { DidKeyPlugin } from "@ucans/core" +import * as crypto from "./crypto.js" +import { P256_DID_PREFIX } from "../prefixes.js" + +export const p256Plugin: DidKeyPlugin = { + prefix: P256_DID_PREFIX, + jwtAlg: "ES256", + verifySignature: async (did: string, data: Uint8Array, sig: Uint8Array) => { + const publicKey = crypto.didToPublicKey(did) + return crypto.verify(publicKey, data, sig) + } +} \ No newline at end of file diff --git a/packages/default-plugins/src/prefixes.ts b/packages/default-plugins/src/prefixes.ts new file mode 100644 index 0000000..2ede29c --- /dev/null +++ b/packages/default-plugins/src/prefixes.ts @@ -0,0 +1,24 @@ +// Each prefix is varint-encoded. So e.g. 0x1205 gets varint-encoded to 0x8524 +// The varint encoding is described here: https://github.com/multiformats/unsigned-varint +// These varints are encoded big-endian in 7-bit pieces. +// So 0x1205 is split up into 0x12 and 0x05 +// Because there's another byte to be read, the MSB of 0x05 is set: 0x85 +// The next 7 bits encode as 0x24 (instead of 0x12) => 0x8524 + +/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L94 */ +export const EDWARDS_DID_PREFIX = new Uint8Array([ 0xed, 0x01 ]) +/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L91 */ +export const BLS_DID_PREFIX = new Uint8Array([ 0xea, 0x01 ]) +/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L141 */ +export const P256_DID_PREFIX = new Uint8Array([ 0x80, 0x24 ]) +/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L142 */ +export const P384_DID_PREFIX = new Uint8Array([ 0x81, 0x24 ]) +/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L143 */ +export const P521_DID_PREFIX = new Uint8Array([ 0x82, 0x24 ]) +/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L146 */ +export const RSA_DID_PREFIX = new Uint8Array([ 0x85, 0x24 ]) +/** Old RSA DID prefix, used pre-standardisation */ +export const RSA_DID_PREFIX_OLD = new Uint8Array([ 0x00, 0xf5, 0x02 ]) + +export const BASE58_DID_PREFIX = "did:key:z" // z is the multibase prefix for base58btc byte encoding + diff --git a/src/crypto/rsa.ts b/packages/default-plugins/src/rsa/crypto.ts similarity index 78% rename from src/crypto/rsa.ts rename to packages/default-plugins/src/rsa/crypto.ts index 1ae1a45..c4be4ca 100644 --- a/src/crypto/rsa.ts +++ b/packages/default-plugins/src/rsa/crypto.ts @@ -1,5 +1,7 @@ import { webcrypto } from "one-webcrypto" import * as uint8arrays from "uint8arrays" +import { RSA_DID_PREFIX, RSA_DID_PREFIX_OLD } from "../prefixes" +import { didFromKeyBytes, keyBytesFromDid } from "../util.js" export const RSA_ALG = "RSASSA-PKCS1-v1_5" export const DEFAULT_KEY_SIZE = 2048 @@ -44,7 +46,7 @@ export const sign = async (msg: Uint8Array, privateKey: CryptoKey): Promise => { +export const verify = async (pubKey: Uint8Array, msg: Uint8Array, sig: Uint8Array): Promise => { return await webcrypto.subtle.verify( { name: RSA_ALG, saltLength: SALT_LEGNTH }, await importKey(pubKey), @@ -53,6 +55,36 @@ export const verify = async (msg: Uint8Array, sig: Uint8Array, pubKey: Uint8Arra ) } +export const didToPublicKey = (did: string): Uint8Array => { + // DID RSA keys are ASN.1 DER encoded "RSAPublicKeys" (PKCS #1). + // But the WebCrypto API mostly works with "SubjectPublicKeyInfo" (SPKI), + // which wraps RSAPublicKey with some metadata. + // In an unofficial RSA multiformat we were using, we used SPKI, + // so we have to be careful not to transform *every* RSA DID to SPKI, but + // only newer DIDs. + const keyBytes = keyBytesFromDid(did, RSA_DID_PREFIX) + return convertRSAPublicKeyToSubjectPublicKeyInfo(keyBytes) +} + +export const oldDidToPublicKey = (did: string): Uint8Array => { + return keyBytesFromDid(did, RSA_DID_PREFIX_OLD) +} + +export const publicKeyToDid = (pubkey: Uint8Array): string => { + // See also the comment in rsaDidToPublicKeyBytes + // In this library, we're assuming a single byte encoding for all types of keys. + // For RSA that is "SubjectPublicKeyInfo", because that's what the WebCrypto API understands. + // But DIDs assume that all public keys are encoded as "RSAPublicKey". + const convertedBytes = convertSubjectPublicKeyInfoToRSAPublicKey(pubkey) + return didFromKeyBytes(convertedBytes, RSA_DID_PREFIX) +} + +export const publicKeyToOldDid = (pubkey: Uint8Array): string => { + return didFromKeyBytes(pubkey, RSA_DID_PREFIX_OLD) +} + + + /** * The ASN.1 DER encoded header that needs to be added to an * ASN.1 DER encoded RSAPublicKey to make it a SubjectPublicKeyInfo. diff --git a/src/keypair/rsa.ts b/packages/default-plugins/src/rsa/keypair.ts similarity index 60% rename from src/keypair/rsa.ts rename to packages/default-plugins/src/rsa/keypair.ts index 296b1bf..0c5dff1 100644 --- a/src/keypair/rsa.ts +++ b/packages/default-plugins/src/rsa/keypair.ts @@ -1,18 +1,23 @@ import { webcrypto } from "one-webcrypto" import * as uint8arrays from "uint8arrays" -import * as rsa from "../crypto/rsa.js" -import BaseKeypair from "./base.js" -import { Encodings, AvailableCryptoKeyPair, isAvailableCryptoKeyPair } from "../types.js" +import * as crypto from "./crypto.js" +import { AvailableCryptoKeyPair, isAvailableCryptoKeyPair } from "../types.js" +import { DidableKey, Encodings, ExportableKey } from "@ucans/core" -export class RsaKeypair extends BaseKeypair { +export class RsaKeypair implements DidableKey, ExportableKey { + public jwtAlg = "RS256" + + private publicKey: Uint8Array private keypair: AvailableCryptoKeyPair + private exportable: boolean constructor(keypair: AvailableCryptoKeyPair, publicKey: Uint8Array, exportable: boolean) { - super(publicKey, "rsa", exportable) this.keypair = keypair + this.publicKey = publicKey + this.exportable = exportable } static async create(params?: { @@ -20,16 +25,20 @@ export class RsaKeypair extends BaseKeypair { exportable?: boolean }): Promise { const { size = 2048, exportable = false } = params || {} - const keypair = await rsa.generateKeypair(size) + const keypair = await crypto.generateKeypair(size) if (!isAvailableCryptoKeyPair(keypair)) { throw new Error(`Couldn't generate valid keypair`) } - const publicKey = await rsa.exportKey(keypair.publicKey) + const publicKey = await crypto.exportKey(keypair.publicKey) return new RsaKeypair(keypair, publicKey, exportable) } + did(): string { + return crypto.publicKeyToDid(this.publicKey) + } + async sign(msg: Uint8Array): Promise { - return await rsa.sign(msg, this.keypair.privateKey) + return await crypto.sign(msg, this.keypair.privateKey) } async export(format: Encodings = "base64pad"): Promise { diff --git a/packages/default-plugins/src/rsa/plugin.ts b/packages/default-plugins/src/rsa/plugin.ts new file mode 100644 index 0000000..f358de0 --- /dev/null +++ b/packages/default-plugins/src/rsa/plugin.ts @@ -0,0 +1,22 @@ +import { DidKeyPlugin } from "@ucans/core" +import * as crypto from "./crypto.js" +import { RSA_DID_PREFIX, RSA_DID_PREFIX_OLD } from "../prefixes.js" + +export const rsaPlugin: DidKeyPlugin = { + prefix: RSA_DID_PREFIX, + jwtAlg: "RS256", + verifySignature: async (did: string, data: Uint8Array, sig: Uint8Array) => { + const publicKey = crypto.didToPublicKey(did) + return crypto.verify(publicKey, data, sig) + } +} + +export const rsaOldPlugin: DidKeyPlugin = { + prefix: RSA_DID_PREFIX_OLD, + jwtAlg: "RS256", + verifySignature: async (did: string, data: Uint8Array, sig: Uint8Array) => { + const publicKey = crypto.oldDidToPublicKey(did) + return crypto.verify(publicKey, data, sig) + } +} + diff --git a/packages/default-plugins/src/types.ts b/packages/default-plugins/src/types.ts new file mode 100644 index 0000000..23489be --- /dev/null +++ b/packages/default-plugins/src/types.ts @@ -0,0 +1,18 @@ +export interface AvailableCryptoKeyPair { + privateKey: CryptoKey + publicKey: CryptoKey +} + +export type PublicKeyJwk = { + kty: string + crv: string + x: string + y: string +} + +export type PrivateKeyJwk = PublicKeyJwk & { d: string } + + +export function isAvailableCryptoKeyPair(keypair: CryptoKeyPair): keypair is AvailableCryptoKeyPair { + return keypair.publicKey != null && keypair.privateKey != null +} \ No newline at end of file diff --git a/packages/default-plugins/src/util.ts b/packages/default-plugins/src/util.ts new file mode 100644 index 0000000..03b5f34 --- /dev/null +++ b/packages/default-plugins/src/util.ts @@ -0,0 +1,32 @@ +import * as uint8arrays from "uint8arrays" +import { BASE58_DID_PREFIX } from "./prefixes.js" + +export function keyBytesFromDid(did: string, expectedPrefix: Uint8Array): Uint8Array { + if (!did.startsWith(BASE58_DID_PREFIX)) { + throw new Error("Please use a base58-encoded DID formatted `did:key:z...`") + } + const didWithoutPrefix = did.slice(BASE58_DID_PREFIX.length) + const bytes = uint8arrays.fromString(didWithoutPrefix, "base58btc") + if(!hasPrefix(bytes, expectedPrefix)) { + throw new Error(`Expected prefix: ${expectedPrefix}`) + } + return bytes.slice(expectedPrefix.length) +} + +export function didFromKeyBytes(publicKeyBytes: Uint8Array, prefix: Uint8Array): string { + const bytes = uint8arrays.concat([prefix, publicKeyBytes]) + const base58Key = uint8arrays.toString(bytes, "base58btc") + return BASE58_DID_PREFIX + base58Key +} + + + +/** + * Determines if a Uint8Array has a given indeterminate length-prefix. + */ +export const hasPrefix = ( + prefixedKey: Uint8Array, + prefix: Uint8Array +): boolean => { + return uint8arrays.equals(prefix, prefixedKey.subarray(0, prefix.byteLength)) +} \ No newline at end of file diff --git a/tests/did-key.ts b/packages/default-plugins/tests/ecdsa.test.ts similarity index 57% rename from tests/did-key.ts rename to packages/default-plugins/tests/ecdsa.test.ts index 9ad2824..214c4c3 100644 --- a/tests/did-key.ts +++ b/packages/default-plugins/tests/ecdsa.test.ts @@ -1,4 +1,31 @@ -import EcdsaKeypair from "../src/keypair/ecdsa.js" +import { p256Plugin } from "../src/p256/plugin.js" +import EcdsaKeypair from "../src/p256/keypair.js" + + +describe("ecdsa", () => { + + let keypair: EcdsaKeypair + let signature: Uint8Array + const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) + + it("creates an ecdsa keypair", async () => { + keypair = await EcdsaKeypair.create() + }) + + it("has the correct JWT alg", async () => { + expect(keypair.jwtAlg).toEqual("ES256") + }) + + it("signs data", async () => { + signature = await keypair.sign(data) + }) + + it("can verify signature", async () => { + const isValid = await p256Plugin.verifySignature(keypair.did(), data, signature) + expect(isValid).toBeTruthy() + }) + +}) // did:key test vectors from W3C // https://github.com/w3c-ccg/did-method-key/blob/main/test-vectors/nist-curves.json @@ -25,7 +52,7 @@ const testVectors = [ } ] -describe("did:key ECDSA P-256", () => { +describe("ecdsa did:key", () => { it("derives the correct DID from the JWK", async () => { for(const vector of testVectors) { const keypair = await EcdsaKeypair.importFromJwk(vector.jwk) diff --git a/packages/default-plugins/tests/ed25519.test.ts b/packages/default-plugins/tests/ed25519.test.ts new file mode 100644 index 0000000..72ee25c --- /dev/null +++ b/packages/default-plugins/tests/ed25519.test.ts @@ -0,0 +1,27 @@ +import { ed25519Plugin } from "../src/ed25519/plugin.js" +import EdwardsKey from "../src/ed25519/keypair.js" + +describe("ed25519", () => { + + let keypair: EdwardsKey + let signature: Uint8Array + const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) + + it("creates an edwards curve keypair", async () => { + keypair = await EdwardsKey.create() + }) + + it("has the correct JWT alg", async () => { + expect(keypair.jwtAlg).toEqual("EdDSA") + }) + + it("signs data", async () => { + signature = await keypair.sign(data) + }) + + it("can verify signature", async () => { + const isValid = await ed25519Plugin.verifySignature(keypair.did(), data, signature) + expect(isValid).toBeTruthy() + }) + +}) diff --git a/tests/rsa.test.ts b/packages/default-plugins/tests/rsa.test.ts similarity index 64% rename from tests/rsa.test.ts rename to packages/default-plugins/tests/rsa.test.ts index 70950ce..e18f279 100644 --- a/tests/rsa.test.ts +++ b/packages/default-plugins/tests/rsa.test.ts @@ -1,8 +1,8 @@ import * as fc from "fast-check" import * as uint8arrays from "uint8arrays" -import * as did from "../src/did" -import * as rsaCrypto from "../src/crypto/rsa" -import RSAKeypair from "../src/keypair/rsa" +import { rsaPlugin } from "../src/rsa/plugin.js" +import * as rsaCrypto from "../src/rsa/crypto.js" +import RSAKeypair from "../src/rsa/keypair.js" describe("rsa", () => { @@ -15,12 +15,8 @@ describe("rsa", () => { keypair = await RSAKeypair.create() }) - it("returns a publicKeyStr and did", () => { - const publicKey = keypair.publicKeyStr() - const keyDid = keypair.did() - const transformed = did.didToPublicKey(keyDid) - expect(transformed.publicKey).toEqual(publicKey) - expect(transformed.type).toEqual("rsa") + it("has the correct JWT alg", async () => { + expect(keypair.jwtAlg).toEqual("RS256") }) it("signs data", async () => { @@ -28,8 +24,16 @@ describe("rsa", () => { }) it("can verify signature", async () => { - const isValid = await did.verifySignature(data, signature, keypair.did()) - expect(isValid).toEqual(true) + const isValid = await rsaPlugin.verifySignature(keypair.did(), data, signature) + expect(isValid).toBeTruthy() + }) + + it("handles old RSA keys", () => { + const toDecode = "did:key:z13V3Sog2YaUKhdGCmgx9UZuW1o1ShFJYc6DvGYe7NTt689NoL2RtpVs65Zw899YrTN9WuxdEEDm54YxWuQHQvcKfkZwa8HTgokHxGDPEmNLhvh69zUMEP4zjuARQ3T8bMUumkSLGpxNe1bfQX624ef45GhWb3S9HM3gvAJ7Qftm8iqnDQVcxwKHjmkV4hveKMTix4bTRhieVHi1oqU4QCVy4QPWpAAympuCP9dAoJFxSP6TNBLY9vPKLazsg7XcFov6UuLWsEaxJ5SomCpDx181mEgW2qTug5oQbrJwExbD9CMgXHLVDE2QgLoQMmgsrPevX57dH715NXC2uY6vo2mYCzRY4KuDRUsrkuYCkewL8q2oK1BEDVvi3Sg8pbC9QYQ5mMiHf8uxiHxTAmPedv8" + const expectedKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB" + const publicKey = rsaCrypto.oldDidToPublicKey(toDecode) + const publicKeyB64 = uint8arrays.toString(publicKey, "base64pad") + expect(publicKeyB64).toEqual(expectedKey) }) }) diff --git a/packages/default-plugins/tsconfig.eslint.json b/packages/default-plugins/tsconfig.eslint.json new file mode 100644 index 0000000..e662081 --- /dev/null +++ b/packages/default-plugins/tsconfig.eslint.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "include": ["**/*.ts"], + "exclude": [] +} diff --git a/packages/default-plugins/tsconfig.json b/packages/default-plugins/tsconfig.json new file mode 100644 index 0000000..c60fdc6 --- /dev/null +++ b/packages/default-plugins/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2015", + "strict": true, + "moduleResolution": "node", + "esModuleInterop": true, + "noFallthroughCasesInSwitch": true, + "allowJs": true + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/packages/ucans/jest.config.ts b/packages/ucans/jest.config.ts new file mode 100644 index 0000000..66af5b0 --- /dev/null +++ b/packages/ucans/jest.config.ts @@ -0,0 +1,3 @@ +import baseConfig from "../../jest.config" + +export default baseConfig diff --git a/packages/ucans/package.json b/packages/ucans/package.json new file mode 100644 index 0000000..b704f41 --- /dev/null +++ b/packages/ucans/package.json @@ -0,0 +1,85 @@ +{ + "name": "@ucans/ucans", + "version": "0.11.0", + "description": "Typescript implementation of UCANs with default plugins", + "author": "Daniel Holmgren ", + "repository": { + "type": "git", + "url": "https://github.com/ucan-wg/ts-ucan" + }, + "homepage": "https://guide.fission.codes", + "license": "Apache-2.0", + "engines": { + "node": ">=15" + }, + "scripts": { + "prebuild": "rimraf dist", + "build": "yarn run dist", + "dev": "tsc --watch --module commonjs --outDir ./dist/cjs/ --sourceMap", + "dist": "yarn run dist:prep && yarn run dist:src && yarn run dist:cjs && yarn run dist:esm && yarn run dist:types && yarn run dist:pkg", + "dist:cjs": "tsc --project ./dist/ --module commonjs --outDir ./dist/cjs/ --sourceMap", + "dist:esm": "tsc --project ./dist/ --module es2020 --outDir ./dist/esm/ --sourceMap", + "dist:pkg": "node ../../scripts/package.js", + "dist:prep": "copyfiles --error tsconfig.json ./dist/", + "dist:src": "copyfiles --error --up 1 \"./src/**/*\" ./dist/src/", + "dist:types": "tsc --project ./dist/ --emitDeclarationOnly --declaration --declarationDir ./dist/types/", + "lint": "eslint src/**/*.ts src/*.ts", + "prepare": "yarn build", + "publish-alpha": "yarn publish --tag alpha", + "publish-stable": "yarn publish --tag latest", + "test": "jest", + "test:watch": "jest --watch" + }, + "exports": { + ".": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js", + "types": "./dist/types/index.d.ts" + }, + "./*.js": { + "import": "./dist/esm/*.js", + "require": "./dist/cjs/*.js", + "types": "./dist/types/*.d.ts" + }, + "./*": { + "import": "./dist/esm/*.js", + "require": "./dist/cjs/*.js", + "types": "./dist/types/*.d.ts" + } + }, + "typesVersions": { + "*": { + "index.d.ts": [ + "dist/types/index.d.ts" + ], + "*": [ + "dist/types/*" + ] + } + }, + "files": [ + "dist", + "docs", + "CHANGELOG.md", + "LICENSE", + "README.md" + ], + "dependencies": { + "@ucans/core": "*", + "@ucans/default-plugins": "*" + }, + "devDependencies": { + "@types/jest": "^27.4.1", + "@types/node": "^17.0.23", + "@typescript-eslint/eslint-plugin": "^5.18.0", + "@typescript-eslint/parser": "^5.18.0", + "copyfiles": "^2.4.1", + "eslint": "^8.12.0", + "fast-check": "^2.24.0", + "jest": "^27.5.1", + "rimraf": "^3.0.2", + "ts-jest": "^27.1.4", + "typescript": "^4.6.3", + "yarn": "^1.22.18" + } +} diff --git a/packages/ucans/src/index.ts b/packages/ucans/src/index.ts new file mode 100644 index 0000000..35cda7e --- /dev/null +++ b/packages/ucans/src/index.ts @@ -0,0 +1,17 @@ +import * as plugins from "@ucans/default-plugins" +import * as core from "@ucans/core" + +export * from "@ucans/core" +export * from "@ucans/default-plugins" + +const injected = core.getPluginInjectedApi(plugins.defaults) + +export const build = injected.build +export const sign = injected.sign +export const signWithKeypair = injected.signWithKeypair +export const validate = injected.validate +export const validateProofs = injected.validateProofs +export const verify = injected.verify +export const Builder = injected.Builder +export const Store = injected.Store +export const delegationChains = injected.delegationChains diff --git a/tests/attenuation.test.ts b/packages/ucans/tests/attenuation.test.ts similarity index 84% rename from tests/attenuation.test.ts rename to packages/ucans/tests/attenuation.test.ts index a798d30..c529595 100644 --- a/tests/attenuation.test.ts +++ b/packages/ucans/tests/attenuation.test.ts @@ -1,8 +1,8 @@ -import * as token from "../src/token" import { emailCapabilities, emailCapability } from "./capability/email" import { alice, bob, mallory } from "./fixtures" -import { all } from "../src/util" +import { all } from "../src" +import * as ucans from "../src" describe("attenuation.emailCapabilities", () => { @@ -11,17 +11,17 @@ describe("attenuation.emailCapabilities", () => { // alice -> bob, bob -> mallory // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [ emailCapability("alice@email.com") ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: [ emailCapability("alice@email.com") ], - proofs: [ token.encode(leafUcan) ] + proofs: [ ucans.encode(leafUcan) ] }) expect(await all(emailCapabilities(ucan))).toEqual([ @@ -40,16 +40,16 @@ describe("attenuation.emailCapabilities", () => { // alice -> bob, bob -> mallory // alice delegates nothing to bob // and bob delegates his email to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: [ emailCapability("bob@email.com") ], - proofs: [ token.encode(leafUcan) ] + proofs: [ ucans.encode(leafUcan) ] }) // we implicitly expect the originator to become bob @@ -63,26 +63,26 @@ describe("attenuation.emailCapabilities", () => { // alice -> mallory, bob -> mallory, mallory -> alice // both alice and bob delegate their email access to mallory // mallory then creates a UCAN with capability to send both - const leafUcanAlice = await token.build({ + const leafUcanAlice = await ucans.build({ issuer: alice, audience: mallory.did(), capabilities: [ emailCapability("alice@email.com") ] }) - const leafUcanBob = await token.build({ + const leafUcanBob = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: [ emailCapability("bob@email.com") ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: mallory, audience: alice.did(), capabilities: [ emailCapability("alice@email.com"), emailCapability("bob@email.com") ], - proofs: [ token.encode(leafUcanAlice), token.encode(leafUcanBob) ] + proofs: [ ucans.encode(leafUcanAlice), ucans.encode(leafUcanBob) ] }) const chains = await all(emailCapabilities(ucan)) @@ -117,23 +117,23 @@ describe("attenuation.emailCapabilities", () => { const aliceEmail = emailCapability("alice@email.com") - const leafUcanAlice = await token.build({ + const leafUcanAlice = await ucans.build({ issuer: alice, audience: mallory.did(), capabilities: [ aliceEmail ] }) - const leafUcanBob = await token.build({ + const leafUcanBob = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: [ aliceEmail ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: mallory, audience: alice.did(), capabilities: [ aliceEmail ], - proofs: [ token.encode(leafUcanAlice), token.encode(leafUcanBob) ] + proofs: [ ucans.encode(leafUcanAlice), ucans.encode(leafUcanBob) ] }) expect(await all(emailCapabilities(ucan))).toEqual([ diff --git a/tests/builder.test.ts b/packages/ucans/tests/builder.test.ts similarity index 82% rename from tests/builder.test.ts rename to packages/ucans/tests/builder.test.ts index 144ec0f..9070bc3 100644 --- a/tests/builder.test.ts +++ b/packages/ucans/tests/builder.test.ts @@ -1,11 +1,9 @@ -import * as token from "../src/token" -import { Builder } from "../src/builder" import { emailCapability } from "./capability/email" import { wnfsCapability, wnfsPublicSemantics } from "./capability/wnfs" import { EMAIL_SEMANTICS } from "./capability/email" import { alice, bob, mallory } from "./fixtures" -import { delegationChains } from "../src/attenuation" -import { first } from "../src/util" +import * as ucans from "../src" +import { first } from "../src" describe("Builder", () => { @@ -18,7 +16,7 @@ describe("Builder", () => { const expiration = Math.floor(Date.now() / 1000) + 30 const notBefore = Math.floor(Date.now() / 1000) - 30 - const ucan = await Builder.create() + const ucan = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withExpiration(expiration) @@ -38,7 +36,7 @@ describe("Builder", () => { }) it("builds with lifetimeInSeconds", async () => { - const payload = Builder.create() + const payload = ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(300) @@ -48,14 +46,14 @@ describe("Builder", () => { }) it("prevents duplicate proofs", async () => { - const ucan = await Builder.create() + const ucan = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .claimCapability(wnfsCapability("alice.fission.name/public/", "SUPER_USER")) .build() - const publicCapability = await first(delegationChains(wnfsPublicSemantics, ucan)) + const publicCapability = await first(ucans.delegationChains(wnfsPublicSemantics, ucan)) if (publicCapability == null) { throw "no capabilities" @@ -65,7 +63,7 @@ describe("Builder", () => { throw publicCapability } - const payload = Builder.create() + const payload = ucans.Builder.create() .issuedBy(bob) .toAudience(mallory.did()) .withLifetimeInSeconds(30) @@ -73,31 +71,31 @@ describe("Builder", () => { .delegateCapability(wnfsCapability("alice.fission.name/public/Documents", "OVERWRITE"), publicCapability, wnfsPublicSemantics) .buildPayload() - expect(payload.prf).toEqual([ token.encode(ucan) ]) + expect(payload.prf).toEqual([ ucans.encode(ucan) ]) }) it("throws when it's not ready to be built", () => { expect(() => { - Builder.create() + ucans.Builder.create() .buildPayload() }).toThrow() // issuer missing expect(() => { - Builder.create() + ucans.Builder.create() .toAudience(bob.did()) .withLifetimeInSeconds(1) .buildPayload() }).toThrow() // audience missing expect(() => { - Builder.create() + ucans.Builder.create() .issuedBy(alice) .withLifetimeInSeconds(1) .buildPayload() }).toThrow() // expiration missing expect(() => { - Builder.create() + ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .buildPayload() @@ -105,14 +103,14 @@ describe("Builder", () => { }) it("throws when trying to delegate unproven capabilities", async () => { - const ucan = await Builder.create() + const ucan = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .claimCapability(emailCapability("alice@email.com")) .build() - const delegationChain = await first(delegationChains(EMAIL_SEMANTICS, ucan)) + const delegationChain = await first(ucans.delegationChains(EMAIL_SEMANTICS, ucan)) if (delegationChain == null) { throw "no capabilities" @@ -123,7 +121,7 @@ describe("Builder", () => { } expect(() => { - Builder.create() + ucans.Builder.create() .issuedBy(bob) .toAudience(mallory.did()) .withLifetimeInSeconds(30) diff --git a/tests/capability/email.ts b/packages/ucans/tests/capability/email.ts similarity index 71% rename from tests/capability/email.ts rename to packages/ucans/tests/capability/email.ts index 63ad868..3537589 100644 --- a/tests/capability/email.ts +++ b/packages/ucans/tests/capability/email.ts @@ -1,10 +1,11 @@ -import { Ucan } from "../../src/types" -import { DelegationSemantics, delegationChains, rootIssuer } from "../../src/attenuation" -import { Ability } from "../../src/capability/ability" -import { Capability } from "../../src/capability" -import { SUPERUSER } from "../../src/capability/super-user" -import { ResourcePointer } from "../../src/capability/resource-pointer" - +import * as ucans from "../../src" +import { + Ucan, + DelegationSemantics, + Ability, + Capability, + ResourcePointer +} from "../../src" // 🌸 @@ -35,10 +36,10 @@ export const EMAIL_SEMANTICS: DelegationSemantics = { }, canDelegateAbility(parentAbility, ability) { - if (parentAbility === SUPERUSER) { + if (parentAbility === ucans.SUPERUSER) { return true } - if (ability === SUPERUSER) { + if (ability === ucans.SUPERUSER) { return false } return parentAbility.namespace === "msg" @@ -70,12 +71,12 @@ export function emailCapability(emailAddress: string): Capability { export async function * emailCapabilities(ucan: Ucan): AsyncIterable<{ capability: EmailCapability; rootIssuer: string }> { - for await (const delegationChain of delegationChains(EMAIL_SEMANTICS, ucan)) { + for await (const delegationChain of ucans.delegationChains(EMAIL_SEMANTICS, ucan)) { if (delegationChain instanceof Error || "ownershipDID" in delegationChain) { continue } yield { - rootIssuer: rootIssuer(delegationChain), + rootIssuer: ucans.rootIssuer(delegationChain), capability: delegationChain.capability } } diff --git a/tests/capability/wnfs.test.ts b/packages/ucans/tests/capability/wnfs.test.ts similarity index 94% rename from tests/capability/wnfs.test.ts rename to packages/ucans/tests/capability/wnfs.test.ts index 58f9bdb..61d030a 100644 --- a/tests/capability/wnfs.test.ts +++ b/packages/ucans/tests/capability/wnfs.test.ts @@ -1,10 +1,8 @@ -import * as token from "../../src/token" -import { Capability } from "../../src/capability" import { wnfsCapability, wnfsPrivateCapabilities, wnfsPublicCapabilities } from "./wnfs" - import { alice, bob, mallory } from "../fixtures" -import { all } from "../../src/util" +import * as ucans from "../../src" +import { Capability, all } from "../../src" describe("wnfs public capability", () => { @@ -190,17 +188,17 @@ describe("wnfs private capability", () => { * The arguments are the capabilities delegated in the first and second arrow, respectively. */ async function makeSimpleDelegation(aliceCapabilities: Capability[], bobCapabilities: Capability[]) { - const leaf = await token.build({ + const leaf = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: aliceCapabilities }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: bobCapabilities, - proofs: [ token.encode(leaf) ] + proofs: [ ucans.encode(leaf) ] }) return { leaf, ucan } @@ -215,23 +213,23 @@ async function makeSimpleDelegation(aliceCapabilities: Capability[], bobCapabili * the second argument are the capabilities delegated in the last arrow. */ async function makeComplexDelegation(proofs: { alice: Capability[]; bob: Capability[] }, final: Capability[]) { - const leafAlice = await token.build({ + const leafAlice = await ucans.build({ issuer: alice, audience: mallory.did(), capabilities: proofs.alice, }) - const leafBob = await token.build({ + const leafBob = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: proofs.bob, }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: mallory, audience: alice.did(), capabilities: final, - proofs: [ token.encode(leafAlice), token.encode(leafBob) ], + proofs: [ ucans.encode(leafAlice), ucans.encode(leafBob) ], }) return { leafAlice, leafBob, ucan } diff --git a/tests/capability/wnfs.ts b/packages/ucans/tests/capability/wnfs.ts similarity index 88% rename from tests/capability/wnfs.ts rename to packages/ucans/tests/capability/wnfs.ts index 68b189f..a0e390e 100644 --- a/tests/capability/wnfs.ts +++ b/packages/ucans/tests/capability/wnfs.ts @@ -1,9 +1,14 @@ -import { Ability, isAbility } from "../../src/capability/ability" -import { Capability } from "../../src/capability" -import { DelegationSemantics, DelegatedCapability, DelegatedOwnership, delegationChains, rootIssuer } from "../../src/attenuation" -import { SUPERUSER } from "../../src/capability/super-user" -import { Ucan } from "../../src/types" -import { ResourcePointer } from "../../src/capability/resource-pointer" +import * as ucans from "../../src" +import { + Ucan, + Capability, + DelegationSemantics, + DelegatedCapability, + DelegatedOwnership, + Ability, + ResourcePointer, + rootIssuer +} from "../../src" export const WNFS_ABILITY_LEVELS = { @@ -23,15 +28,15 @@ export function isWnfsCap(cap: Capability): boolean { } export function isWnfsAbility(ability: unknown): ability is WnfsAbility { - if (!isAbility(ability)) return false - if (ability === SUPERUSER) return true + if (!ucans.isAbility(ability)) return false + if (ability === ucans.SUPERUSER) return true const abilitySegment = ability.segments[ 0 ] const isWnfsAbilitySegment = !!abilitySegment && WNFS_ABILITIES.includes(abilitySegment) return isWnfsAbilitySegment && ability.namespace.toLowerCase() === "wnfs" } export function wnfsAbilityFromAbility(ability: Ability): WnfsAbility | null { - if (ability === SUPERUSER) return "SUPER_USER" + if (ability === ucans.SUPERUSER) return "SUPER_USER" if (isWnfsAbility(ability)) return ability.segments[ 0 ] as WnfsAbility return null } @@ -118,7 +123,7 @@ export const wnfsPublicSemantics: DelegationSemantics = { } export async function * wnfsPublicCapabilities(ucan: Ucan) { - for await (const delegationChain of delegationChains(wnfsPublicSemantics, ucan)) { + for await (const delegationChain of ucans.delegationChains(wnfsPublicSemantics, ucan)) { if (delegationChain instanceof Error || "ownershipDID" in delegationChain) { continue } @@ -189,7 +194,7 @@ const wnfsPrivateSemantics: DelegationSemantics = { } export async function * wnfsPrivateCapabilities(ucan: Ucan) { - for await (const delegationChain of delegationChains(wnfsPrivateSemantics, ucan)) { + for await (const delegationChain of ucans.delegationChains(wnfsPrivateSemantics, ucan)) { if (delegationChain instanceof Error || "ownershipDID" in delegationChain) { continue } diff --git a/tests/compatibility.test.ts b/packages/ucans/tests/compatibility.test.ts similarity index 98% rename from tests/compatibility.test.ts rename to packages/ucans/tests/compatibility.test.ts index fca9af9..1ef419f 100644 --- a/tests/compatibility.test.ts +++ b/packages/ucans/tests/compatibility.test.ts @@ -1,5 +1,5 @@ import * as uint8arrays from "uint8arrays" -import * as token from "../src/token" +import * as ucans from "../src" const oldUcan = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVhdiI6IjEuMC4wIn0.eyJhdWQiOiJkaWQ6a2V5OnoxM1YzU29nMllhVUtoZEdDbWd4OVVadVcxbzFTaEZKWWM2RHZHWWU3TlR0Njg5Tm9MMXRrZUd3NGMydGFQa2dBdWloUjh0cmg2azg2VHRVaTNIR2ZrNEh1NDg3czNiTWY4V1MzWjJoU3VwRktiNmhnV3VwajFIRzhheUxRdDFmeWJSdThjTGdBMkNKanFRYm16YzRFOEFKU0tKeDNndVFYa2F4c3R2Um5RRGN1eDFkZzhVR1BRS3haN2lLeUFKWkFuQlcyWXJUM2o0TVQxdTJNcWZQWG9RYU01WFZQMk04clBFN0FCSEREOXdMbWlKdjkzUUFDRFR5MllnZkVSS3JualNWaTdFb3RNOFR3NHg3M1pNUXJEQnZRRW01Zm9tTWZVaTZVSmJUTmVaaldDTUJQYllNbXRKUDZQZlRpaWZYZG0zdXprVFg5NnExUkVFOExodkU2Rzg2cUR0Wjg5MzdFYUdXdXFpNkRHVDFvc2FRMUVnR3NFN3Jac2JSdDFLNnRXeTZpYktlNTlKZWtnTWFlNW9XNER2IiwiZXhwIjozMjc0NDE5MTQyMywiZmN0IjpbXSwiaXNzIjoiZGlkOmtleTp6MTNWM1NvZzJZYVVLaGRHQ21neDlVWnVXMW8xU2hGSlljNkR2R1llN05UdDY4OU5vTDJWanZBR2JXdTFrdmZWUWFyVTVWMXBTUnNjOWFwR2h2dDdaODJmUWg1QWE1NW41Zm0zZGs2SnFuTXczZGU4WG91dWZUV2Z1eHpEVkhrSFNGV0sxOW1SWWI4d205d1VwZkxtUWl4QVdtMndFWVZqU2dENEd6YzhVUDlDSjFxMkY4ZXlpVXViMThGbld4Y2djUWhqdXB3OTNxUlMzWDlXUDViemlSYjE4TTZ0Vm8zaUJ4ZUozb2lrRTNaa3RScEtTZDlkcHU5WWNXZFhoeDZDQmY5NTZ1UXhkTDZoTkppNmVMbmZ1eFY2NEhpZU1rZFVoTTJSeThRd3lqZjQ4ZnZWMVhFVU1zeEM5YWFjNEtCcGJONDJHR3U4UmFkRDU3cjZuMWFOc2IyTjU3RkNOYnFIMXVLdHhNTmVHZHJ2QWlUUGRzVjJBRmppczJvN243ajhMNW41YmJ4TFl4VThNVHB3QVphdFpkSiIsIm5iZiI6MTY0MDE5MTQ1NywicHJmIjoiZXlKaGJHY2lPaUpTVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0lzSW5WaGRpSTZJakV1TUM0d0luMC5leUpoZFdRaU9pSmthV1E2YTJWNU9ub3hNMVl6VTI5bk1sbGhWVXRvWkVkRGJXZDRPVlZhZFZjeGJ6RlRhRVpLV1dNMlJIWkhXV1UzVGxSME5qZzVUbTlNTWxacWRrRkhZbGQxTVd0MlpsWlJZWEpWTlZZeGNGTlNjMk01WVhCSGFIWjBOMW80TW1aUmFEVkJZVFUxYmpWbWJUTmthelpLY1c1TmR6TmtaVGhZYjNWMVpsUlhablY0ZWtSV1NHdElVMFpYU3pFNWJWSlpZamgzYlRsM1ZYQm1URzFSYVhoQlYyMHlkMFZaVm1wVFowUTBSM3BqT0ZWUU9VTktNWEV5UmpobGVXbFZkV0l4T0VadVYzaGpaMk5SYUdwMWNIYzVNM0ZTVXpOWU9WZFFOV0o2YVZKaU1UaE5OblJXYnpOcFFuaGxTak52YVd0Rk0xcHJkRkp3UzFOa09XUndkVGxaWTFka1dHaDROa05DWmprMU5uVlJlR1JNTm1oT1NtazJaVXh1Wm5WNFZqWTBTR2xsVFd0a1ZXaE5NbEo1T0ZGM2VXcG1ORGhtZGxZeFdFVlZUWE40UXpsaFlXTTBTMEp3WWs0ME1rZEhkVGhTWVdSRU5UZHlObTR4WVU1ellqSk9OVGRHUTA1aWNVZ3hkVXQwZUUxT1pVZGtjblpCYVZSUVpITldNa0ZHYW1sek1tODNiamRxT0V3MWJqVmlZbmhNV1hoVk9FMVVjSGRCV21GMFdtUktJaXdpWlhod0lqb3pNamMwTkRFNU1UUXlNeXdpWm1OMElqcGJYU3dpYVhOeklqb2laR2xrT210bGVUcDZNVE5XTTFOdlp6SlpZVlZMYUdSSFEyMW5lRGxWV25WWE1XOHhVMmhHU2xsak5rUjJSMWxsTjA1VWREWTRPVTV2VERKaE5VcE9hMlI0VmpabWJYVm9WbU5SWkRkSVIycHhkRXBRYVc1WlZWQTRRMUp4Y21veVkyVm5hVTFyT1RKUlNIazJRbWRXT1hveVVGQnJWMkZZU0RkUlRsQmlRekphZEUxNWFXbGFjWGRLUkVOd05sZG9VbkZVUzJodVFtaENUbWQ1WkRkTFJuUTNjRkkyTkhCa1ZIQjZUbXRNUlZKNGFHNTNUVUZqZURKcVJGZFlOelpDVG5SS04xUTFWVXQ0TTIxcWRHWTBaak0wWjJwVGRUaHJkME5UY0V0alFuQTRWV2RwU0hkdllVSkhkREUxVkZjNVUzQlNXVkoxYUZKdk1tdEljVFZ5Y0ROTmRFSnFSa2QyVUdZeVRsTlpZbUUzTmxoSGJYcFhlVEZyZUZOelEySTVUSGhqTW5welEwdG1lSEF5ZUd0VVFqWmtPVVJDUlVwVE5sUnhXbFo1WkhKU05GWmFNVkE1ZFhJeGRGcHBlbk5qYWtWd1kzVlViV1EzV0VRemRYSjZVelpqY0RSdU1sZHdSbFZNYjNsMk5tOW5ibWxaZEVOSGFUVlVlbWxEY2pKT1FWRjNWMEZYY25CMldVMWllbVEyVmt0a2RUVmpaekZZUWxoTVZFNWhUQ0lzSW01aVppSTZNVFkwTURFNU1UTTJNeXdpY0hSaklqb2lVMVZRUlZKZlZWTkZVaUlzSW5Kell5STZJaW9pZlEuQ0k5SjlOLVhUZUxQNEM5WTktUl9TcEE1aE80dHdpNUQxNFpTR2lwUzdjNS1jTlJWTVItc285Z0JZMlQzSFNaTHFmQ2xyMEtlQVJicFk2TFBwSm1NRGQ1ODdvck1TVVRnMndqN043eUNVeksxSWhOazhQMkQ3RGVlSHNxQ1lsTVotdXpjMHBSbnFJb3dPTWl6MVFkbHZXaTZ0UHNxZkZVYnl4bEx1bXRHdjV1a1hqc1FZcmYzdko3aU5DMkJibWotMGhTV25wNTNBN01TQTllLWFXVGpLUWEwSkpXVVVhWG5XS19CNjRaa3NyTWRXdW5mVFNuSE9lR2o3MFRuSXhieVcxbFhodk5pcnhIUV90ZVlKZ2xIZTRBbldEQXdUa2dnaVotdkp0WUhsYnVwQkt4S1YtNm9OMTlXS3dUT3U3QnpPX2QyUHAtWVVyY1RSSS1KZ0F2NUpnIiwicHRjIjoiU1VQRVJfVVNFUiIsInJzYyI6IioifQ.CRLB4gBBHhnsbfUhLALiCfo6mHnHSlEUczyZsWhh9TNjv9UxdgvsSWQsehGIT4XR0jQeYZo2OhasEVaF-Gtt_qqtUQIrducKngd0qzmpfjVbicsQPKVdJjlcTwm9dqhLSEtL195El0oucLzYdqMEZMf-txEmyhCd_Q8CaNExhAnwN32v1salnO6vrAw33ZJID7ZaFmBleoGUXBHQwnkv9_m_P6Fh-UGIKjaOuNmBkGXGn-4irm-eXrne2OPZCoPjhiaf0xTONu4ROrQQYykG8CppvsSXeiylOFY11Ot0sdAlHGSlyZk1_chJ3ud17K9S-CKWK9NtqiMNcUdQGFnNQQ" @@ -9,9 +9,8 @@ const header = JSON.parse(uint8arrays.toString(uint8arrays.fromString(encodedHea const payload = JSON.parse(uint8arrays.toString(uint8arrays.fromString(encodedPayload, "base64url"))) describe("compatibility", () => { - it("allows parsing UCANs with 'uav: 1.0.0' into 'ucv: 0.3.0'", async () => { - const ucan = await token.validate(oldUcan, { checkIsExpired: false, checkIsTooEarly: false, checkSignature: false }) + const ucan = await ucans.validate(oldUcan, { checkIsExpired: false, checkIsTooEarly: false, checkSignature: false }) expect(ucan).toEqual({ header: { alg: header.alg, // "RS256", diff --git a/tests/fixtures.ts b/packages/ucans/tests/fixtures.ts similarity index 93% rename from tests/fixtures.ts rename to packages/ucans/tests/fixtures.ts index fbdeeb1..73348ca 100644 --- a/tests/fixtures.ts +++ b/packages/ucans/tests/fixtures.ts @@ -1,5 +1,4 @@ -import { EdKeypair } from "../src/keypair/ed25519" - +import { EdKeypair } from "@ucans/default-plugins" /** did:key:z6Mkk89bC3JrVqKie71YEcc5M1SMVxuCgNx6zLZ8SYJsxALi */ export const alice = EdKeypair.fromSecretKey("U+bzp2GaFQHso587iSFWPSeCzbSfn/CbNHEz7ilKRZ1UQMmMS7qq4UhTzKn3X9Nj/4xgrwa+UqhMOeo4Ki8JUw==") diff --git a/tests/store.test.ts b/packages/ucans/tests/store.test.ts similarity index 65% rename from tests/store.test.ts rename to packages/ucans/tests/store.test.ts index da7864f..7c8fa36 100644 --- a/tests/store.test.ts +++ b/packages/ucans/tests/store.test.ts @@ -1,57 +1,52 @@ -import * as token from "../src/token" -import { Store } from "../src/store" -import { Builder } from "../src/builder" import { alice, bob, mallory } from "./fixtures" import { wnfsCapability, wnfsPublicSemantics } from "./capability/wnfs" -import { Ucan } from "../src/types" -import { equalCanDelegate } from "../src/attenuation" -import { all } from "../src/util" - +import * as ucans from "../src" +import { Ucan, all } from "../src" describe("Store.add", () => { it("makes added items retrievable with findByAudience", async () => { - const ucan = await Builder.create() + const ucan = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .build() - const encoded = token.encode(ucan) + const encoded = ucans.encode(ucan) - const store = await Store.fromTokens(equalCanDelegate, []) + const store = await ucans.Store.empty(ucans.equalCanDelegate) await store.add(ucan) - expect(encodeOrNull(store.findByAudience(ucan.payload.aud, find => token.encode(find) === encoded))).toEqual(encoded) + expect(encodeOrNull(store.findByAudience(ucan.payload.aud, find => ucans.encode(find) === encoded))).toEqual(encoded) }) it("makes added items retrievable with findByAudience among multiple others", async () => { - const ucan = await Builder.create() + const ucan = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .build() - const ucan2 = await Builder.create() + const ucan2 = await ucans.Builder.create() .issuedBy(alice) .toAudience(mallory.did()) .withLifetimeInSeconds(30) .build() - const encoded = token.encode(ucan) - const store = await Store.fromTokens(equalCanDelegate, []) + const encoded = ucans.encode(ucan) + const store = await ucans.Store.empty(ucans.equalCanDelegate) await store.add(ucan2) await store.add(ucan) - expect(encodeOrNull(store.findByAudience(ucan.payload.aud, find => token.encode(find) === encoded))).toEqual(encoded) + expect(encodeOrNull(store.findByAudience(ucan.payload.aud, find => ucans.encode(find) === encoded))).toEqual(encoded) }) it("doesn't add items twice", async () => { - const ucan = await Builder.create() + const ucan = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .build() - const store = await Store.fromTokens(equalCanDelegate, []) + const store = await ucans.Store.empty(ucans.equalCanDelegate) await store.add(ucan) await store.add(ucan) expect(store.getByAudience(ucan.payload.aud)).toEqual([ ucan ]) @@ -62,22 +57,22 @@ describe("Store.add", () => { describe("Store.findByAudience", () => { it("only returns ucans with given audience", async () => { - const ucanBob = await Builder.create() + const ucanBob = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .build() - const ucanAlice = await Builder.create() + const ucanAlice = await ucans.Builder.create() .issuedBy(bob) .toAudience(alice.did()) .withLifetimeInSeconds(30) .build() - const store = await Store.fromTokens(equalCanDelegate, [ ucanBob, ucanAlice ].map(ucan => token.encode(ucan))) + const store = await ucans.Store.fromTokens(ucans.equalCanDelegate, [ ucanBob, ucanAlice ].map(ucan => ucans.encode(ucan))) expect(store.findByAudience(mallory.did(), () => true)).toEqual(null) - expect(encodeOrNull(store.findByAudience(bob.did(), () => true))).toEqual(token.encode(ucanBob)) - expect(encodeOrNull(store.findByAudience(alice.did(), () => true))).toEqual(token.encode(ucanAlice)) + expect(encodeOrNull(store.findByAudience(bob.did(), () => true))).toEqual(ucans.encode(ucanBob)) + expect(encodeOrNull(store.findByAudience(alice.did(), () => true))).toEqual(ucans.encode(ucanAlice)) }) }) @@ -85,14 +80,14 @@ describe("Store.findByAudience", () => { describe("Store.findWithCapability", () => { it("finds ucans with more capabilities than the given", async () => { - const ucan = await Builder.create() + const ucan = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .claimCapability(wnfsCapability("alice.fission.name/public/", "SUPER_USER")) .build() - const store = await Store.fromTokens(wnfsPublicSemantics, [ token.encode(ucan) ]) + const store = await ucans.Store.fromTokens(wnfsPublicSemantics, [ ucans.encode(ucan) ]) const results = all(store.findWithCapability( bob.did(), @@ -104,24 +99,24 @@ describe("Store.findWithCapability", () => { throw "no capability" } - expect(encodeOrNull(results[0]?.ucan)).toEqual(token.encode(ucan)) + expect(encodeOrNull(results[0]?.ucan)).toEqual(ucans.encode(ucan)) }) it("reports an error if the capability can't be found with given audience", async () => { - const ucanBob = await Builder.create() + const ucanBob = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .claimCapability(wnfsCapability("alice.fission.name/public/", "SUPER_USER")) .build() - const ucanAlice = await Builder.create() + const ucanAlice = await ucans.Builder.create() .issuedBy(alice) .toAudience(bob.did()) .withLifetimeInSeconds(30) .build() - const store = await Store.fromTokens(wnfsPublicSemantics, [ token.encode(ucanAlice), token.encode(ucanBob) ]) + const store = await ucans.Store.fromTokens(wnfsPublicSemantics, [ ucans.encode(ucanAlice), ucans.encode(ucanBob) ]) const results = all(store.findWithCapability( alice.did(), @@ -138,5 +133,5 @@ function encodeOrNull(ucan: Ucan | null): string { if (ucan == null) { return "null" } - return token.encode(ucan) + return ucans.encode(ucan) } diff --git a/tests/token.test.ts b/packages/ucans/tests/token.test.ts similarity index 71% rename from tests/token.test.ts rename to packages/ucans/tests/token.test.ts index b625a78..7062879 100644 --- a/tests/token.test.ts +++ b/packages/ucans/tests/token.test.ts @@ -1,18 +1,16 @@ import * as uint8arrays from "uint8arrays" - -import * as capability from "../src/capability" -import * as token from "../src/token" -import { verifySignatureUtf8 } from "../src/did" import { alice, bob } from "./fixtures" - +import * as ucans from "../src" // COMPOSING describe("token.build", () => { + // beforeAll(loadTestPlugins) + it("can build payloads without nbf", () => { - const payload = token.buildPayload({ + const payload = ucans.buildPayload({ issuer: alice.did(), audience: bob.did(), }) @@ -20,7 +18,7 @@ describe("token.build", () => { }) it("builds payloads that expire in the future", () => { - const payload = token.buildPayload({ + const payload = ucans.buildPayload({ issuer: alice.did(), audience: bob.did(), @@ -31,12 +29,12 @@ describe("token.build", () => { it("throws when enclosing tokens with an invalid key type", async () => { await expect(() => { - const payload = token.buildPayload({ + const payload = ucans.buildPayload({ issuer: alice.did(), audience: bob.did(), }) - return token.sign( + return ucans.sign( payload, "rsa", data => alice.sign(data) @@ -59,13 +57,13 @@ describe("token.encodePayload", () => { can: "crud/DELETE" } - const payload = token.buildPayload({ + const payload = ucans.buildPayload({ issuer: alice.did(), audience: bob.did(), - capabilities: [ capability.parse(encodedCaps) ] + capabilities: [ ucans.capability.parse(encodedCaps) ] }) - const encoded = token.encodePayload(payload) + const encoded = ucans.encodePayload(payload) const decodedString = uint8arrays.toString( uint8arrays.fromString(encoded, "base64url"), "utf8" @@ -88,8 +86,9 @@ describe("token.encodePayload", () => { describe("token.validate", () => { + async function makeUcan() { - return await token.build({ + return await ucans.build({ audience: bob.did(), issuer: alice, capabilities: [ @@ -111,7 +110,7 @@ describe("token.validate", () => { it("round-trips with token.build", async () => { const ucan = await makeUcan() - const parsedUcan = await token.validate(token.encode(ucan)) + const parsedUcan = await ucans.validate(ucans.encode(ucan)) expect(parsedUcan).toBeDefined() }) @@ -121,8 +120,8 @@ describe("token.validate", () => { ...ucan.payload, aud: "fakeaudience" } - const badUcan = `${token.encodeHeader(ucan.header)}.${token.encodePayload(badPayload)}.${ucan.signature}` - await expect(() => token.validate(badUcan)).rejects.toBeDefined() + const badUcan = `${ucans.encodeHeader(ucan.header)}.${ucans.encodePayload(badPayload)}.${ucan.signature}` + await expect(() => ucans.validate(badUcan)).rejects.toBeDefined() }) it("throws with a bad issuer", async () => { @@ -131,8 +130,8 @@ describe("token.validate", () => { ...ucan.header, alg: "RS256" } - const badUcan = `${token.encodeHeader(badHeader)}.${token.encodePayload(ucan.payload)}.${ucan.signature}` - await expect(() => token.validate(badUcan)).rejects.toBeDefined() + const badUcan = `${ucans.encodeHeader(badHeader)}.${ucans.encodePayload(ucan.payload)}.${ucan.signature}` + await expect(() => ucans.validate(badUcan)).rejects.toBeDefined() }) it("identifies a ucan that is not active yet", async () => { @@ -145,7 +144,7 @@ describe("token.validate", () => { exp: 2637352774 } } - expect(token.isTooEarly(badUcan)).toBe(true) + expect(ucans.isTooEarly(badUcan)).toBe(true) }) it("identifies a ucan that has become active", async () => { @@ -158,18 +157,6 @@ describe("token.validate", () => { lifetimeInSeonds: 30 } } - expect(token.isTooEarly(activeUcan)).toBe(false) - }) -}) - -describe("verifySignatureUtf8", () => { - - it("works with an example", async () => { - const [ header, payload, signature ] = token.encode(await token.build({ - issuer: alice, - audience: bob.did(), - })).split(".") - expect(await verifySignatureUtf8(`${header}.${payload}`, signature, alice.did())).toEqual(true) + expect(ucans.isTooEarly(activeUcan)).toBe(false) }) - -}) +}) \ No newline at end of file diff --git a/tests/verify.test.ts b/packages/ucans/tests/verify.test.ts similarity index 72% rename from tests/verify.test.ts rename to packages/ucans/tests/verify.test.ts index ba91658..cc78603 100644 --- a/tests/verify.test.ts +++ b/packages/ucans/tests/verify.test.ts @@ -1,11 +1,6 @@ -import * as token from "../src/token" -import * as capability from "../src/capability" -import { SUPERUSER } from "../src/capability/super-user" -import { verify } from "../src/verify" import { emailCapability } from "./capability/email" import { alice, bob, mallory } from "./fixtures" -import { REDELEGATE } from "../src/capability/ability" - +import * as ucans from "../src" describe("verify", () => { @@ -13,22 +8,22 @@ describe("verify", () => { // alice -> bob, bob -> mallory // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), expiration, capabilities: [ emailCapability("alice@email.com") ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), expiration, capabilities: [ emailCapability("alice@email.com") ], - proofs: [ token.encode(leafUcan) ] + proofs: [ ucans.encode(leafUcan) ] }) - return token.encode(ucan) + return ucans.encode(ucan) } const alicesEmail = { @@ -39,7 +34,7 @@ describe("verify", () => { it("verifies a delegation chain", async () => { const ucan = await aliceEmailDelegationExample() - const result = await verify(ucan, { + const result = await ucans.verify(ucan, { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) @@ -59,12 +54,12 @@ describe("verify", () => { it("rejects an invalid escalation", async () => { const ucan = await aliceEmailDelegationExample() - const result = await verify(ucan, { + const result = await ucans.verify(ucan, { audience: mallory.did(), requiredCapabilities: [ { capability: { ...emailCapability("alice@email.com"), - can: SUPERUSER, + can: ucans.SUPERUSER, }, rootIssuer: alice.did() } ] @@ -76,7 +71,7 @@ describe("verify", () => { it("rejects for an invalid audience", async () => { const ucan = await aliceEmailDelegationExample() - const result = await verify(ucan, { + const result = await ucans.verify(ucan, { audience: bob.did(), requiredCapabilities: [ alicesEmail ] }) @@ -87,7 +82,7 @@ describe("verify", () => { it("rejects for an invalid rootIssuer", async () => { const ucan = await aliceEmailDelegationExample() - const result = await verify(ucan, { + const result = await ucans.verify(ucan, { audience: mallory.did(), requiredCapabilities: [ { capability: emailCapability("alice@email.com"), @@ -105,7 +100,7 @@ describe("verify", () => { // expiry is in the past const ucan = await aliceEmailDelegationExample(nowInSeconds - 60 * 60 * 24) - const result = await verify(ucan, { + const result = await ucans.verify(ucan, { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) @@ -117,20 +112,20 @@ describe("verify", () => { // alice -> bob // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [ emailCapability("alice@email.com") ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), - capabilities: [ capability.prf(capability.superUser.SUPERUSER, REDELEGATE) ], - proofs: [ token.encode(leafUcan) ] + capabilities: [ ucans.capability.prf(ucans.SUPERUSER, ucans.ability.REDELEGATE) ], + proofs: [ ucans.encode(leafUcan) ] }) - const result = await verify(token.encode(ucan), { + const result = await ucans.verify(ucans.encode(ucan), { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) @@ -147,26 +142,26 @@ describe("verify", () => { // alice -> bob // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcanA = await token.build({ + const leafUcanA = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [ emailCapability("ignore-me@email.com") ] }) - const leafUcanB = await token.build({ + const leafUcanB = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [ emailCapability("alice@email.com") ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), - capabilities: [ capability.prf(1, REDELEGATE) ], - proofs: [ token.encode(leafUcanA), token.encode(leafUcanB) ] + capabilities: [ ucans.capability.prf(1, ucans.ability.REDELEGATE) ], + proofs: [ ucans.encode(leafUcanA), ucans.encode(leafUcanB) ] }) - const result = await verify(token.encode(ucan), { + const result = await ucans.verify(ucans.encode(ucan), { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) @@ -180,26 +175,26 @@ describe("verify", () => { }) it("ignores other proofs not referred to by `prf:0`", async () => { - const leafUcanA = await token.build({ + const leafUcanA = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [ emailCapability("ignore-me@email.com") ] }) - const leafUcanB = await token.build({ + const leafUcanB = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [ emailCapability("alice@email.com") ] }) - const faultyUcan = await token.build({ + const faultyUcan = await ucans.build({ issuer: bob, audience: mallory.did(), - capabilities: [ capability.prf(0, REDELEGATE) ], - proofs: [ token.encode(leafUcanA), token.encode(leafUcanB) ] + capabilities: [ ucans.capability.prf(0, ucans.ability.REDELEGATE) ], + proofs: [ ucans.encode(leafUcanA), ucans.encode(leafUcanB) ] }) - const result = await verify(token.encode(faultyUcan), { + const result = await ucans.verify(ucans.encode(faultyUcan), { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) @@ -211,20 +206,20 @@ describe("verify", () => { // alice -> bob // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [ emailCapability("invalid@email.com") ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), - capabilities: [ capability.prf(capability.superUser.SUPERUSER, REDELEGATE) ], - proofs: [ token.encode(leafUcan) ] + capabilities: [ ucans.capability.prf(ucans.SUPERUSER, ucans.ability.REDELEGATE) ], + proofs: [ ucans.encode(leafUcan) ] }) - const result = await verify(token.encode(ucan), { + const result = await ucans.verify(ucans.encode(ucan), { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) @@ -236,20 +231,20 @@ describe("verify", () => { // alice -> bob // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), - capabilities: [ capability.my(capability.superUser.SUPERUSER) ] + capabilities: [ ucans.capability.my(ucans.SUPERUSER) ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: [ emailCapability("alice@email.com") ], - proofs: [ token.encode(leafUcan) ] + proofs: [ ucans.encode(leafUcan) ] }) - const result = await verify(token.encode(ucan), { + const result = await ucans.verify(ucans.encode(ucan), { audience: mallory.did(), requiredCapabilities: [ alicesEmail ], }) @@ -265,27 +260,27 @@ describe("verify", () => { // alice -> bob, bob -> mallory, mallory -> "someone" // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), - capabilities: [ capability.my(capability.superUser.SUPERUSER) ] + capabilities: [ ucans.capability.my(ucans.SUPERUSER) ] }) - const middleUcan = await token.build({ + const middleUcan = await ucans.build({ issuer: bob, audience: mallory.did(), - capabilities: [ capability.as(alice.did(), SUPERUSER) ], - proofs: [ token.encode(leafUcan) ] + capabilities: [ ucans.capability.as(alice.did(), ucans.SUPERUSER) ], + proofs: [ ucans.encode(leafUcan) ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: mallory, audience: "did:key:someone", capabilities: [ emailCapability("alice@email.com") ], - proofs: [ token.encode(middleUcan) ] + proofs: [ ucans.encode(middleUcan) ] }) - const result = await verify(token.encode(ucan), { + const result = await ucans.verify(ucans.encode(ucan), { audience: "did:key:someone", requiredCapabilities: [ alicesEmail ] }) @@ -301,20 +296,20 @@ describe("verify", () => { // alice -> bob // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), capabilities: [] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: [ emailCapability("alice@email.com") ], - proofs: [ token.encode(leafUcan) ] + proofs: [ ucans.encode(leafUcan) ] }) - const result = await verify(token.encode(ucan), { + const result = await ucans.verify(ucans.encode(ucan), { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) @@ -326,20 +321,20 @@ describe("verify", () => { // alice -> bob // alice delegates access to sending email as her to bob // and bob delegates it further to mallory - const leafUcan = await token.build({ + const leafUcan = await ucans.build({ issuer: alice, audience: bob.did(), - capabilities: [ capability.as(bob.did(), SUPERUSER) ] + capabilities: [ ucans.capability.as(bob.did(), ucans.SUPERUSER) ] }) - const ucan = await token.build({ + const ucan = await ucans.build({ issuer: bob, audience: mallory.did(), capabilities: [ emailCapability("alice@email.com") ], - proofs: [ token.encode(leafUcan) ] + proofs: [ ucans.encode(leafUcan) ] }) - const result = await verify(token.encode(ucan), { + const result = await ucans.verify(ucans.encode(ucan), { audience: mallory.did(), requiredCapabilities: [ alicesEmail ] }) diff --git a/packages/ucans/tsconfig.eslint.json b/packages/ucans/tsconfig.eslint.json new file mode 100644 index 0000000..e662081 --- /dev/null +++ b/packages/ucans/tsconfig.eslint.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "include": ["**/*.ts"], + "exclude": [] +} diff --git a/packages/ucans/tsconfig.json b/packages/ucans/tsconfig.json new file mode 100644 index 0000000..c60fdc6 --- /dev/null +++ b/packages/ucans/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2015", + "strict": true, + "moduleResolution": "node", + "esModuleInterop": true, + "noFallthroughCasesInSwitch": true, + "allowJs": true + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/src/builder.ts b/src/builder.ts deleted file mode 100644 index b5831d7..0000000 --- a/src/builder.ts +++ /dev/null @@ -1,289 +0,0 @@ -import * as token from "./token.js" -import * as util from "./util.js" - -import { Keypair, Fact, UcanPayload, isKeypair, Ucan } from "./types.js" -import { Capability, isCapability } from "./capability/index.js" -import { capabilityCanBeDelegated, DelegationSemantics, DelegationChain } from "./attenuation.js" -import { Store } from "./store.js" -import { publicKeyBytesToDid } from "./did/transformers.js" - - -export interface BuildableState { - issuer: Keypair - audience: string - expiration: number -} - -function isBuildableState(obj: unknown): obj is BuildableState { - return util.isRecord(obj) - && util.hasProp(obj, "issuer") && isKeypair(obj.issuer) - && util.hasProp(obj, "audience") && typeof obj.audience === "string" - && util.hasProp(obj, "expiration") && typeof obj.expiration === "number" -} - -interface DefaultableState { - capabilities: Capability[] - facts: Fact[] - proofs: Ucan[] - addNonce: boolean - notBefore?: number -} - -// the state neccessary for being able to lookup fitting capabilities in the UCAN store -export interface CapabilityLookupCapableState { - issuer: Keypair - expiration: number -} - -function isCapabilityLookupCapableState(obj: unknown): obj is CapabilityLookupCapableState { - return util.isRecord(obj) - && util.hasProp(obj, "issuer") && isKeypair(obj.issuer) - && util.hasProp(obj, "expiration") && typeof obj.expiration === "number" -} - -/** - * A builder API for UCANs. - * - * Supports grabbing UCANs from a UCAN `Store` for proofs (see `delegateCapability`). - * - * Example usage: - * - * ```ts - * const ucan = await Builder.create() - * .issuedBy(aliceKeypair) - * .toAudience(bobDID) - * .withLifetimeInSeconds(30) - * .claimCapability({ email: "my@email.com", cap: "SEND" }) - * .delegateCapability(emailSemantics, { email: "my-friends@email.com", cap: "SEND" }, proof) - * .build() - * ``` - */ -export class Builder> { - - private state: State // portion of the state that's required to be set before building - private defaultable: DefaultableState // portion of the state that has sensible defaults - - private constructor(state: State, defaultable: DefaultableState) { - this.state = state - this.defaultable = defaultable - } - - /** - * Create an empty builder. - * Before finalising the builder, you need to at least call - * - `issuedBy` - * - `toAudience` and - * - `withLifetimeInSeconds` or `withExpiration`. - * To finalise the builder, call its `build` or `buildPayload` method. - */ - static create(): Builder> { - return new Builder({}, { capabilities: [], facts: [], proofs: [], addNonce: false }) - } - - /** - * @param issuer The issuer as a DID string ("did:key:..."). - * - * The UCAN must be signed with the private key of the issuer to be valid. - */ - issuedBy(issuer: Keypair): Builder { - if (!isKeypair(issuer)) { - throw new TypeError(`Expected a Keypair, but got ${issuer}`) - } - return new Builder({ ...this.state, issuer }, this.defaultable) - } - - /** - * @param audience The audience as a DID string ("did:key:..."). - * - * This is the identity this UCAN transfers rights to. - * It could e.g. be the DID of a service you're posting this UCAN as a JWT to, - * or it could be the DID of something that'll use this UCAN as a proof to - * continue the UCAN chain as an issuer. - */ - toAudience(audience: string): Builder { - if (typeof audience !== "string") { - throw new TypeError(`Expected audience DID as string, but got ${audience}`) - } - return new Builder({ ...this.state, audience }, this.defaultable) - } - - /** - * @param seconds The number of seconds from the calltime of this function - * to set the expiry timestamp to. - */ - withLifetimeInSeconds(seconds: number): Builder { - if (typeof seconds !== "number") { - throw new TypeError(`Expected seconds as number, but got ${seconds}`) - } - if (!isFinite(seconds) || seconds <= 0) { - throw new TypeError(`Expected seconds to be a positive number, but got ${seconds}`) - } - return this.withExpiration(Math.floor(Date.now() / 1000) + seconds) - } - - /** - * @param expiration The UTCTime timestamp (in seconds) for when the UCAN should expire. - */ - withExpiration(expiration: number): Builder { - if (typeof expiration !== "number" || !isFinite(expiration)) { - throw new TypeError(`Expected expiration as number, but got ${expiration}`) - } - if (this.defaultable.notBefore != null && expiration < this.defaultable.notBefore) { - throw new Error(`Can't set expiration to ${expiration} which is before 'notBefore': ${this.defaultable.notBefore}`) - } - return new Builder({ ...this.state, expiration }, this.defaultable) - } - - /** - * @param notBeforeTimestamp The UTCTime timestamp (in seconds) of when the UCAN becomes active. - */ - withNotBefore(notBeforeTimestamp: number): Builder { - if (typeof notBeforeTimestamp !== "number" || !isFinite(notBeforeTimestamp)) { - throw new TypeError(`Expected notBeforeTimestamp as number, but got ${notBeforeTimestamp}`) - } - if (util.hasProp(this.state, "expiration") && typeof this.state.expiration === "number" && this.state.expiration < notBeforeTimestamp) { - throw new Error(`Can't set 'notBefore' to ${notBeforeTimestamp} which is after expiration: ${this.state.expiration}`) - } - return new Builder(this.state, { ...this.defaultable, notBefore: notBeforeTimestamp }) - } - - /** - * @param fact Any fact or proof of knowledge in this UCAN as a record. - * @param facts Arbitrary more facts or proofs of knowledge. - */ - withFact(fact: Fact): Builder - withFact(fact: Fact, ...facts: Fact[]): Builder - withFact(fact: Fact, ...facts: Fact[]): Builder { - if (!util.isRecord(fact) || facts.some(fct => !util.isRecord(fct))) { - throw new TypeError(`Expected fact(s) to be a record, but got ${fact}`) - } - return new Builder(this.state, { - ...this.defaultable, - facts: [ ...this.defaultable.facts, fact, ...facts ] - }) - } - - /** - * Will ensure that the built UCAN includes a number used once. - */ - withNonce(): Builder { - return new Builder(this.state, { ...this.defaultable, addNonce: true }) - } - - /** - * Claim capabilities 'by parenthood'. - */ - claimCapability(capability: Capability): Builder - claimCapability(capability: Capability, ...capabilities: Capability[]): Builder - claimCapability(capability: Capability, ...capabilities: Capability[]): Builder { - if (!isCapability(capability)) { - throw new TypeError(`Expected capability, but got ${JSON.stringify(capability, null, " ")}`) - } - return new Builder(this.state, { - ...this.defaultable, - capabilities: [ ...this.defaultable.capabilities, capability, ...capabilities ] - }) - } - - /** - * Delegate capabilities from a given proof to the audience of the UCAN you're building. - * - * @param semantics The rules for which delegations of capabilities are allowed. - * @param requiredCapability The capability you want to delegate. - * - * Then, one of - * @param proof The proof chain that grants the issuer of this UCAN at least the capabilities you want to delegate, or - * @param store The UCAN store in which to try to find a UCAN granting you enough capabilities to delegate given capabilities. - * - * @throws If given store can't provide a UCAN for delegating given capability - * @throws If given proof can't be used to delegate given capability - * @throws If the builder hasn't set an issuer and expiration yet - */ - delegateCapability(requiredCapability: Capability, store: Store): State extends CapabilityLookupCapableState ? Builder : never - delegateCapability(requiredCapability: Capability, proof: DelegationChain, semantics: DelegationSemantics): State extends CapabilityLookupCapableState ? Builder : never - delegateCapability(requiredCapability: Capability, storeOrProof: Store | DelegationChain, semantics?: DelegationSemantics): Builder { - if (!isCapability(requiredCapability)) { - throw new TypeError(`Expected 'requiredCapability' as a second argument, but got ${requiredCapability}`) - } - if (!isCapabilityLookupCapableState(this.state)) { - throw new Error(`Can't delegate capabilities without having these paramenters set in the builder: issuer and expiration.`) - } - - function isProof(proof: Store | DelegationChain): proof is DelegationChain { - return util.hasProp(proof, "capability") || util.hasProp(proof, "ownershipDID") - } - - if (isProof(storeOrProof)) { - if (semantics == null) { - throw new TypeError(`Expected 'semantics' as third argument if a 'proof' DelegationChain was passed as second.`) - } - const proof: DelegationChain = storeOrProof - const ucan = proof.ucan - if (!capabilityCanBeDelegated(semantics, requiredCapability, proof)) { - throw new Error(`Can't add capability to UCAN: Given proof doesn't give required rights to delegate.`) - } - return new Builder(this.state, { - ...this.defaultable, - capabilities: [ ...this.defaultable.capabilities, requiredCapability ], - proofs: this.defaultable.proofs.find(p => token.encode(p) === token.encode(ucan)) == null - ? [ ...this.defaultable.proofs, ucan ] - : this.defaultable.proofs - }) - } else { - const store: Store = storeOrProof - const issuer = publicKeyBytesToDid(this.state.issuer.publicKey, this.state.issuer.keyType) - // we look up a proof that has our issuer as an audience - const result = util.first(store.findWithCapability(issuer, requiredCapability, issuer)) - if (result != null) { - const ucan = result.ucan - const ucanEncoded = token.encode(ucan) - return new Builder(this.state, { - ...this.defaultable, - capabilities: [ ...this.defaultable.capabilities, requiredCapability ], - proofs: this.defaultable.proofs.find(proof => token.encode(proof) === ucanEncoded) == null - ? [ ...this.defaultable.proofs, ucan ] - : this.defaultable.proofs - }) - } else { - throw new Error(`Couldn't add capability to UCAN. Couldn't find anything providing this capability in given store.`) - } - } - } - - /** - * Build the UCAN body. This can be used if you want to sign the UCAN yourself afterwards. - */ - buildPayload(): State extends BuildableState ? UcanPayload : never - buildPayload(): UcanPayload { - if (!isBuildableState(this.state)) { - throw new Error(`Builder is missing one of the required properties before it can be built: issuer, audience and expiration.`) - } - return token.buildPayload({ - issuer: publicKeyBytesToDid(this.state.issuer.publicKey, this.state.issuer.keyType), - audience: this.state.audience, - - expiration: this.state.expiration, - notBefore: this.defaultable.notBefore, - addNonce: this.defaultable.addNonce, - - capabilities: this.defaultable.capabilities, - facts: this.defaultable.facts, - proofs: this.defaultable.proofs.map(proof => token.encode(proof)), - }) - } - - /** - * Finalize: Build and sign the UCAN. - * - * @throws If the builder hasn't yet been set an issuer, audience and expiration. - */ - async build(): Promise - async build(): Promise { - if (!isBuildableState(this.state)) { - throw new Error(`Builder is missing one of the required properties before it can be built: issuer, audience and expiration.`) - } - const payload = this.buildPayload() - return await token.signWithKeypair(payload, this.state.issuer) - } - -} diff --git a/src/crypto/ecdsa.ts b/src/crypto/ecdsa.ts deleted file mode 100644 index 91df05a..0000000 --- a/src/crypto/ecdsa.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { webcrypto } from "one-webcrypto" -import { NamedCurve, KeyType, PrivateKeyJwk } from "../types.js" - -export const ALG = "ECDSA" -export const DEFAULT_CURVE = "P-256" -export const DEFAULT_HASH_ALG = "SHA-256" - -export const generateKeypair = async ( - namedCurve: NamedCurve = DEFAULT_CURVE -): Promise => { - return await webcrypto.subtle.generateKey( - { - name: ALG, - namedCurve, - }, - false, - [ "sign", "verify" ] - ) -} - -export const importKeypairJwk = async ( - privKeyJwk: PrivateKeyJwk, - namedCurve: NamedCurve = DEFAULT_CURVE, - exportable = false -): Promise => { - const privateKey = await webcrypto.subtle.importKey( - "jwk", - privKeyJwk, - { - name: ALG, - namedCurve, - }, - exportable, - ["sign" ] - ) - const { kty, crv, x, y} = privKeyJwk - const pubKeyJwk = { kty, crv, x, y} - const publicKey = await webcrypto.subtle.importKey( - "jwk", - pubKeyJwk, - { - name: ALG, - namedCurve, - }, - true, - [ "verify" ] - ) - return { privateKey, publicKey } -} - -export const exportKey = async (key: CryptoKey): Promise => { - const buf = await webcrypto.subtle.exportKey("raw", key) - return new Uint8Array(buf) -} - -export const importKey = async ( - key: Uint8Array, - namedCurve: NamedCurve -): Promise => { - return await webcrypto.subtle.importKey( - "raw", - key.buffer, - { name: ALG, namedCurve }, - true, - [ "verify" ] - ) -} - -export const sign = async ( - msg: Uint8Array, - privateKey: CryptoKey -): Promise => { - const buf = await webcrypto.subtle.sign( - { name: ALG, hash: { name: DEFAULT_HASH_ALG } }, - privateKey, - msg.buffer - ) - return new Uint8Array(buf) -} - -export const verify = async ( - msg: Uint8Array, - sig: Uint8Array, - pubKey: Uint8Array, - namedCurve: NamedCurve -): Promise => { - return await webcrypto.subtle.verify( - { name: ALG, hash: { name: DEFAULT_HASH_ALG } }, - await importKey(pubKey, namedCurve), - sig.buffer, - msg.buffer - ) -} - -export const toKeyType = (namedCurve: NamedCurve): KeyType => { - switch (namedCurve) { - case "P-256": - return "p256" - default: - throw new Error(`Unsupported namedCurve: ${namedCurve}`) - } -} diff --git a/src/crypto/index.ts b/src/crypto/index.ts deleted file mode 100644 index 716bc77..0000000 --- a/src/crypto/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as rsa from "./rsa.js" -export * as ecdsa from "./ecdsa.js" diff --git a/src/did.ts b/src/did.ts deleted file mode 100644 index 3161ab5..0000000 --- a/src/did.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./did/prefix.js" -export * from "./did/transformers.js" -export * from "./did/validation.js" diff --git a/src/did/prefix.ts b/src/did/prefix.ts deleted file mode 100644 index c0063c5..0000000 --- a/src/did/prefix.ts +++ /dev/null @@ -1,106 +0,0 @@ -import * as uint8arrays from "uint8arrays" -import * as compression from "./pubkey-compress.js" -import { KeyType } from "../types.js" - -// Each prefix is varint-encoded. So e.g. 0x1205 gets varint-encoded to 0x8524 -// The varint encoding is described here: https://github.com/multiformats/unsigned-varint -// These varints are encoded big-endian in 7-bit pieces. -// So 0x1205 is split up into 0x12 and 0x05 -// Because there's another byte to be read, the MSB of 0x05 is set: 0x85 -// The next 7 bits encode as 0x24 (instead of 0x12) => 0x8524 - -/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L94 */ -export const EDWARDS_DID_PREFIX = new Uint8Array([ 0xed, 0x01 ]) -/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L91 */ -export const BLS_DID_PREFIX = new Uint8Array([ 0xea, 0x01 ]) -/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L141 */ -export const P256_DID_PREFIX = new Uint8Array([ 0x80, 0x24 ]) -/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L142 */ -export const P384_DID_PREFIX = new Uint8Array([ 0x81, 0x24 ]) -/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L143 */ -export const P521_DID_PREFIX = new Uint8Array([ 0x82, 0x24 ]) -/** https://github.com/multiformats/multicodec/blob/e9ecf587558964715054a0afcc01f7ace220952c/table.csv#L146 */ -export const RSA_DID_PREFIX = new Uint8Array([ 0x85, 0x24 ]) -/** Old RSA DID prefix, used pre-standardisation */ -export const RSA_DID_PREFIX_OLD = new Uint8Array([ 0x00, 0xf5, 0x02 ]) - -export const BASE58_DID_PREFIX = "did:key:z" // z is the multibase prefix for base58btc byte encoding - -/** - * Magic bytes. - */ -export function magicBytes(keyType: KeyType): Uint8Array | null { - switch (keyType) { - case "ed25519": - return EDWARDS_DID_PREFIX - case "p256": - return P256_DID_PREFIX - case "rsa": - return RSA_DID_PREFIX - case "bls12-381": - return BLS_DID_PREFIX - default: - return null - } -} - -/** - * Parse magic bytes on prefixed key-bytes - * to determine cryptosystem & the unprefixed key-bytes. - */ -export const parseMagicBytes = ( - prefixedKey: Uint8Array -): { - keyBytes: Uint8Array - type: KeyType -} => { - // RSA - if (hasPrefix(prefixedKey, RSA_DID_PREFIX)) { - return { - keyBytes: prefixedKey.slice(RSA_DID_PREFIX.byteLength), - type: "rsa", - } - - // RSA OLD - } else if (hasPrefix(prefixedKey, RSA_DID_PREFIX_OLD)) { - return { - keyBytes: prefixedKey.slice(RSA_DID_PREFIX_OLD.byteLength), - type: "rsa", - } - - // EC P-256 - } else if (hasPrefix(prefixedKey, P256_DID_PREFIX)) { - const compressedKey = prefixedKey.slice(P256_DID_PREFIX.byteLength) - const keyBytes = compression.decompressNistP256Pubkey(compressedKey) - return { - keyBytes, - type: "p256", - } - - // EDWARDS - } else if (hasPrefix(prefixedKey, EDWARDS_DID_PREFIX)) { - return { - keyBytes: prefixedKey.slice(EDWARDS_DID_PREFIX.byteLength), - type: "ed25519", - } - - // BLS - } else if (hasPrefix(prefixedKey, BLS_DID_PREFIX)) { - return { - keyBytes: prefixedKey.slice(BLS_DID_PREFIX.byteLength), - type: "bls12-381", - } - } - - throw new Error("Unsupported key algorithm. Try using RSA.") -} - -/** - * Determines if a Uint8Array has a given indeterminate length-prefix. - */ -export const hasPrefix = ( - prefixedKey: Uint8Array, - prefix: Uint8Array -): boolean => { - return uint8arrays.equals(prefix, prefixedKey.subarray(0, prefix.byteLength)) -} diff --git a/src/did/pubkey-compress.ts b/src/did/pubkey-compress.ts deleted file mode 100644 index fe9f7c2..0000000 --- a/src/did/pubkey-compress.ts +++ /dev/null @@ -1,78 +0,0 @@ -import bigInt from "big-integer" -import * as uint8arrays from "uint8arrays" - -// Compression & Decompression algos from: -// https://stackoverflow.com/questions/48521840/biginteger-to-a-uint8array-of-bytes - -// Public key compression for NIST P-256 -export const compressNistP256Pubkey = (pubkeyBytes: Uint8Array): Uint8Array => { - if (pubkeyBytes.length !== 65) { - throw new Error("Expected 65 byte pubkey") - } else if (pubkeyBytes[0] !== 0x04) { - throw new Error("Expected first byte to be 0x04") - } - // first byte is a prefix - const x = pubkeyBytes.slice(1, 33) - const y = pubkeyBytes.slice(33, 65) - const out = new Uint8Array(x.length + 1) - - out[0] = 2 + (y[y.length - 1] & 1) - out.set(x, 1) - - return out -} - -// Public key decompression for NIST P-256 -export const decompressNistP256Pubkey = (compressed: Uint8Array): Uint8Array => { - if (compressed.length !== 33) { - throw new Error("Expected 33 byte compress pubkey") - } else if (compressed[0] !== 0x02 && compressed[0] !== 0x03) { - throw new Error("Expected first byte to be 0x02 or 0x03") - } - // Consts for P256 curve - const two = bigInt(2) - // 115792089210356248762697446949407573530086143415290314195533631308867097853951 - const prime = two - .pow(256) - .subtract(two.pow(224)) - .add(two.pow(192)) - .add(two.pow(96)) - .subtract(1) - const b = bigInt( - "41058363725152142129326129780047268409114441015993725554835256314039467401291", - ) - - // Pre-computed value, or literal - const pIdent = prime.add(1).divide(4) // 28948022302589062190674361737351893382521535853822578548883407827216774463488 - - // This value must be 2 or 3. 4 indicates an uncompressed key, and anything else is invalid. - const signY = bigInt(compressed[0] - 2) - const x = compressed.slice(1) - const xBig = bigInt(uint8arrays.toString(x, "base10")) - - // y^2 = x^3 - 3x + b - const maybeY = xBig - .pow(3) - .subtract(xBig.multiply(3)) - .add(b) - .modPow(pIdent, prime) - - let yBig - // If the parity matches, we found our root, otherwise it's the other root - if (maybeY.mod(2).equals(signY)) { - yBig = maybeY - } else { - // y = prime - y - yBig = prime.subtract(maybeY) - } - const y = uint8arrays.fromString(yBig.toString(10), "base10") - - // left-pad for smaller than 32 byte y - const offset = 32 - y.length - const yPadded = new Uint8Array(32) - yPadded.set(y, offset) - - // concat coords & prepend P-256 prefix - const publicKey = uint8arrays.concat([[0x04], x, yPadded]) - return publicKey -} diff --git a/src/did/transformers.ts b/src/did/transformers.ts deleted file mode 100644 index 65fb2a0..0000000 --- a/src/did/transformers.ts +++ /dev/null @@ -1,105 +0,0 @@ -import * as uint8arrays from "uint8arrays" - -import * as compression from "./pubkey-compress.js" -import * as rsa from "../crypto/rsa.js" -import { BASE58_DID_PREFIX, RSA_DID_PREFIX_OLD, magicBytes, parseMagicBytes, hasPrefix } from "./prefix.js" -import { KeyType, Encodings } from "../types.js" - - -// DID → PUBLIC KEY - - -/** - * Convert a DID (did:key) to a base64 public key. - */ -export function didToPublicKey(did: string, encoding: Encodings = "base64pad"): { - publicKey: string - type: KeyType -} { - const { publicKey, type } = didToPublicKeyBytes(did) - return { - publicKey: uint8arrays.toString(publicKey, encoding), - type - } -} - -/** - * Convert a DID (did:key) to the public key into bytes in SubjectPublicKeyInfo (spki) format. - * - * For consumption e.g. in the WebCrypto API. - */ -export function didToPublicKeyBytes(did: string): { - publicKey: Uint8Array - type: KeyType -} { - if (!did.startsWith(BASE58_DID_PREFIX)) { - throw new Error("Please use a base58-encoded DID formatted `did:key:z...`") - } - - const didWithoutPrefix = did.slice(BASE58_DID_PREFIX.length) - const magicBytes = uint8arrays.fromString(didWithoutPrefix, "base58btc") - const parsed = parseMagicBytes(magicBytes) - - if (parsed.type === "rsa" && !hasPrefix(magicBytes, RSA_DID_PREFIX_OLD)) { - // DID RSA keys are ASN.1 DER encoded "RSAPublicKeys" (PKCS #1). - // But the WebCrypto API mostly works with "SubjectPublicKeyInfo" (SPKI), - // which wraps RSAPublicKey with some metadata. - // In an unofficial RSA multiformat we were using, we used SPKI, - // so we have to be careful not to transform *every* RSA DID to SPKI, but - // only newer DIDs. - parsed.keyBytes = rsa.convertRSAPublicKeyToSubjectPublicKeyInfo(parsed.keyBytes) - } - - return { - publicKey: parsed.keyBytes, - type: parsed.type, - } -} - - - -// PUBLIC KEY → DID - - -/** - * Convert a base64 public key to a DID (did:key). - */ -export function publicKeyToDid( - publicKey: string, - type: KeyType, - encoding: Encodings = "base64pad" -): string { - const pubKeyBytes = uint8arrays.fromString(publicKey, encoding) - return publicKeyBytesToDid(pubKeyBytes, type) -} - -/** - * Convert a public key in bytes to a DID (did:key). - */ -export function publicKeyBytesToDid( - publicKeyBytes: Uint8Array, - type: KeyType, -): string { - // Prefix public-write key - const prefix = magicBytes(type) - if (prefix === null) { - throw new Error(`Key type '${type}' not supported`) - } - - if (type === "rsa") { - // See also the comment in didToPublicKeyBytes - // In this library, we're assuming a single byte encoding for all types of keys. - // For RSA that is "SubjectPublicKeyInfo", because that's what the WebCrypto API understands. - // But DIDs assume that all public keys are encoded as "RSAPublicKey". - publicKeyBytes = rsa.convertSubjectPublicKeyInfoToRSAPublicKey(publicKeyBytes) - } - - if(type === "p256") { - publicKeyBytes = compression.compressNistP256Pubkey(publicKeyBytes) - } - - const prefixedBytes = uint8arrays.concat([ prefix, publicKeyBytes ]) - - // Encode prefixed - return BASE58_DID_PREFIX + uint8arrays.toString(prefixedBytes, "base58btc") -} diff --git a/src/did/validation.ts b/src/did/validation.ts deleted file mode 100644 index f472617..0000000 --- a/src/did/validation.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as ed25519 from "@stablelib/ed25519" -import * as uint8arrays from "uint8arrays" - -import * as rsa from "../crypto/rsa.js" -import * as ecdsa from "../crypto/ecdsa.js" - -import { didToPublicKeyBytes } from "./transformers.js" - - -/** - * Verify the signature of some data (Uint8Array), given a DID. - */ -export async function verifySignature(data: Uint8Array, signature: Uint8Array, did: string): Promise { - try { - const { type, publicKey } = didToPublicKeyBytes(did) - - switch (type) { - - case "ed25519": - return ed25519.verify(publicKey, data, signature) - - case "rsa": - return await rsa.verify(data, signature, publicKey) - - case "p256": - return await ecdsa.verify(data, signature, publicKey, "P-256") - - default: return false - } - - } catch (_) { - return false - - } -} - -/** - * Verify the signature of some data (string encoded as utf8), given a DID. - */ -export async function verifySignatureUtf8(data: string, signature: string, did: string): Promise { - const dataBytes = uint8arrays.fromString(data, "utf8") - const sigBytes = uint8arrays.fromString(signature, "base64url") - return await verifySignature(dataBytes, sigBytes, did) -} diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 7f0180e..0000000 --- a/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -export * from "./attenuation.js" -export * from "./builder.js" -export * from "./did.js" -export * from "./keypair/ed25519.js" -export * from "./keypair/rsa.js" -export * from "./store.js" -export * from "./token.js" -export * from "./types.js" -export * from "./verify.js" - -export * as keypair from "./keypair/index.js" -export * as capability from "./capability/index.js" - -export { Capability, EncodedCapability, isCapability } from "./capability/index.js" \ No newline at end of file diff --git a/src/keypair/base.ts b/src/keypair/base.ts deleted file mode 100644 index f4081cf..0000000 --- a/src/keypair/base.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as uint8arrays from "uint8arrays" - -import { publicKeyBytesToDid } from "../did/transformers.js" -import { Keypair, KeyType, Encodings, Didable, ExportableKey } from "../types.js" - - -export default abstract class BaseKeypair implements Keypair, Didable, ExportableKey { - - publicKey: Uint8Array - keyType: KeyType - exportable: boolean - - constructor(publicKey: Uint8Array, keyType: KeyType, exportable: boolean) { - this.publicKey = publicKey - this.keyType = keyType - this.exportable = exportable - } - - publicKeyStr(encoding: Encodings = "base64pad"): string { - return uint8arrays.toString(this.publicKey, encoding) - } - - did(): string { - return publicKeyBytesToDid(this.publicKey, this.keyType) - } - - abstract sign(msg: Uint8Array): Promise - abstract export(): Promise -} diff --git a/src/keypair/index.ts b/src/keypair/index.ts deleted file mode 100644 index f230746..0000000 --- a/src/keypair/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./ed25519.js" -export * from "./ecdsa.js" -export * from "./rsa.js" -export * from "./base.js" diff --git a/src/store.ts b/src/store.ts deleted file mode 100644 index aa9560d..0000000 --- a/src/store.ts +++ /dev/null @@ -1,92 +0,0 @@ -import * as token from "./token.js" -import { capabilityCanBeDelegated, DelegationSemantics, DelegationChain, delegationChains, rootIssuer } from "./attenuation.js" -import { Ucan } from "./types.js" -import { Capability } from "./capability/index.js" - - -export interface IndexByAudience { - [ audienceDID: string ]: Array<{ - processedUcan: Ucan - capabilities: DelegationChain[] - }> -} - -export class Store { - - private index: IndexByAudience - private knownSemantics: DelegationSemantics - - constructor(knownSemantics: DelegationSemantics, index: IndexByAudience) { - this.index = index - this.knownSemantics = knownSemantics - } - - static async fromTokens(knownSemantics: DelegationSemantics, tokens: Iterable | AsyncIterable): Promise { - const store = new Store(knownSemantics, {}) - for await (const encodedUcan of tokens) { - const ucan = await token.validate(encodedUcan) - await store.add(ucan) - } - return store - } - - async add(ucan: Ucan): Promise { - const audience = ucan.payload.aud - const byAudience = this.index[ audience ] ?? [] - const encoded = token.encode(ucan) - - if (byAudience.find(stored => token.encode(stored.processedUcan) === encoded) != null) { - return - } - - const chains = [] - for await (const delegationChain of delegationChains(this.knownSemantics, ucan)) { - if (delegationChain instanceof Error) { - console.warn(`Delegation chain error while storing UCAN:`, delegationChain) - continue - } - chains.push(delegationChain) - } - - // Also do this *after* the all awaits to prevent races. - if (byAudience.find(stored => token.encode(stored.processedUcan) === encoded) != null) { - return - } - - byAudience.push({ - processedUcan: ucan, - capabilities: chains - }) - this.index[ audience ] = byAudience - } - - getByAudience(audience: string): Ucan[] { - return (this.index[ audience ] ?? []).map(elem => elem.processedUcan) - } - - findByAudience(audience: string, predicate: (ucan: Ucan) => boolean): Ucan | null { - return this.index[ audience ]?.find(elem => predicate(elem.processedUcan))?.processedUcan ?? null - } - - *findWithCapability( - audience: string, - requiredCapability: Capability, - requiredIssuer: string, - ): Iterable { - const cache = this.index[ audience ] - - if (cache == null) { - return - } - - for (const cacheElement of cache) { - for (const delegationChain of cacheElement.capabilities) { - if (capabilityCanBeDelegated(this.knownSemantics, requiredCapability, delegationChain) - && rootIssuer(delegationChain) === requiredIssuer) { - yield delegationChain - } - } - } - } - -} diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index e0bd5bf..0000000 --- a/src/types.ts +++ /dev/null @@ -1,136 +0,0 @@ -import * as semver from "./semver.js" -import { SemVer } from "./semver.js" -import { SupportedEncodings } from "uint8arrays/util/bases.js" -import { Capability, isCapability, isEncodedCapability } from "./capability/index.js" -import * as util from "./util.js" - - -// 💎 - - -export type Ucan = { - header: UcanHeader - payload: UcanPayload - // We need to keep the encoded version around to preserve the signature - signedData: string - signature: string -} - - - -// CHUNKS - - -export interface UcanParts { - header: UcanHeader - payload: UcanPayload -} - -export type UcanHeader = { - alg: string - typ: string - ucv: SemVer -} - -export type UcanPayload = { - iss: string - aud: string - exp: number - nbf?: number - nnc?: string - att: Array - fct?: Array - prf: Array -} - - - -// FRAGMENTS - - -export type Fact = Record - - - -// CRYPTOGRAPHY - - -/** Unlike tslib's CryptoKeyPair, this requires the `privateKey` and `publicKey` fields */ -export interface AvailableCryptoKeyPair { - privateKey: CryptoKey - publicKey: CryptoKey -} - -export interface Didable { - publicKeyStr: (format?: Encodings) => string - did: () => string -} - -export interface ExportableKey { - export: (format?: Encodings) => Promise -} - -export interface Keypair { - publicKey: Uint8Array - keyType: KeyType - sign: (msg: Uint8Array) => Promise -} - -export type KeyType = - | "rsa" - | "p256" - | "ed25519" - | "bls12-381" - -// https://developer.mozilla.org/en-US/docs/Web/API/EcKeyGenParams -export type NamedCurve = "P-256" - -export type PublicKeyJwk = { - kty: string - crv: string - x: string - y: string -} - -export type PrivateKeyJwk = PublicKeyJwk & { d: string } - - -// MISC - - -export type Encodings = SupportedEncodings - - - -// TYPE CHECKS - - -export function isAvailableCryptoKeyPair(keypair: CryptoKeyPair): keypair is AvailableCryptoKeyPair { - return keypair.publicKey != null && keypair.privateKey != null -} - -export function isKeypair(obj: unknown): obj is Keypair { - return util.isRecord(obj) - && util.hasProp(obj, "publicKey") && obj.publicKey instanceof Uint8Array - && util.hasProp(obj, "keyType") && typeof obj.keyType === "string" - && util.hasProp(obj, "sign") && typeof obj.sign === "function" -} - -export function isUcanHeader(obj: unknown): obj is UcanHeader { - return util.isRecord(obj) - && util.hasProp(obj, "alg") && typeof obj.alg === "string" - && util.hasProp(obj, "typ") && typeof obj.typ === "string" - && util.hasProp(obj, "ucv") && semver.isSemVer(obj.ucv) -} - -export function isUcanPayload(obj: unknown): obj is UcanPayload { - return util.isRecord(obj) - && util.hasProp(obj, "iss") && typeof obj.iss === "string" - && util.hasProp(obj, "aud") && typeof obj.aud === "string" - && util.hasProp(obj, "exp") && typeof obj.exp === "number" - && (!util.hasProp(obj, "nbf") || typeof obj.nbf === "number") - && (!util.hasProp(obj, "nnc") || typeof obj.nnc === "string") - && util.hasProp(obj, "att") && Array.isArray(obj.att) && obj.att.every(a => isCapability(a) || isEncodedCapability(a)) - && (!util.hasProp(obj, "fct") || Array.isArray(obj.fct) && obj.fct.every(util.isRecord)) - && util.hasProp(obj, "prf") && Array.isArray(obj.prf) && obj.prf.every(str => typeof str === "string") -} diff --git a/tests/did.test.ts b/tests/did.test.ts deleted file mode 100644 index 02abca7..0000000 --- a/tests/did.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as did from "../src/did" - -describe("publicKeyToDid", () => { - - it("handles RSA Keys", async () => { - const pubkey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB" - // old: const expectedDid = "did:key:z13V3Sog2YaUKhdGCmgx9UZuW1o1ShFJYc6DvGYe7NTt689NoL2RtpVs65Zw899YrTN9WuxdEEDm54YxWuQHQvcKfkZwa8HTgokHxGDPEmNLhvh69zUMEP4zjuARQ3T8bMUumkSLGpxNe1bfQX624ef45GhWb3S9HM3gvAJ7Qftm8iqnDQVcxwKHjmkV4hveKMTix4bTRhieVHi1oqU4QCVy4QPWpAAympuCP9dAoJFxSP6TNBLY9vPKLazsg7XcFov6UuLWsEaxJ5SomCpDx181mEgW2qTug5oQbrJwExbD9CMgXHLVDE2QgLoQMmgsrPevX57dH715NXC2uY6vo2mYCzRY4KuDRUsrkuYCkewL8q2oK1BEDVvi3Sg8pbC9QYQ5mMiHf8uxiHxTAmPedv8" - const expectedDid = "did:key:z4MXj1wBzi9jUstyNvmiK5WLRRL4rr9UvzPxhry1CudCLKWLyMbP1WoTwDfttBTpxDKf5hAJEjqNbeYx2EEvrJmSWHAu7TJRPTrE3QodbMfRvRNRDyYvaN1FSQus2ziS1rWXwAi5Gpc16bY3JwjyLCPJLfdRWHZhRXiay5FWEkfoSKy6aftnzAvqNkKBg2AxgzGMinR6d1WiH4w5mEXFtUeZkeo4uwtRTd8rD9BoVaHVkGwJkksDybE23CsBNXiNfbweFVRcwfTMhcQsTsYhUWDcSC6QE3zt9h4Rsrj7XRYdwYSK5bc1qFRsg5HULKBp2uZ1gcayiW2FqHFcMRjBieC4LnSMSD1AZB1WUncVRbPpVkn1UGhCU" - const result = did.publicKeyToDid(pubkey, "rsa") - expect(result).toEqual(expectedDid) - }) - - it("handles Ed25519 Keys", async () => { - const pubkey = "Hv+AVRD2WUjUFOsSNbsmrp9fokuwrUnjBcr92f0kxw4=" - const expectedDid = "did:key:z6MkgYGF3thn8k1Fv4p4dWXKtsXCnLH7q9yw4QgNPULDmDKB" - const result = did.publicKeyToDid(pubkey, "ed25519") - expect(result).toEqual(expectedDid) - }) - - it("handles BLS12-381 Keys", async () => { - const pubkey = "Hv+AVRD2WUjUFOsSNbsmrp9fokuwrUnjBcr92f0kxw4=" - const expectedDid = "did:key:z6HpYD1br5P4QVh5rjRGAkBfKMWes44uhKmKdJ6dN2Nm9gHK" - const result = did.publicKeyToDid(pubkey, "bls12-381") - expect(result).toEqual(expectedDid) - }) - - it("handles NIST P-256 Keys", async () => { - const pubkey = "BEgg6smRlRQXKqzJHu0w5/nHcy7zYNxFXwTKUyyCOoDMztUvQn5VZg668v4MecHGUZTeHkaZhSraK7RtJuXfWp4=" - const expectedDid = "did:key:zDnaeVHXWgKUpJFc8AUfRDuRWfsAQejmZu5HrERh41iGumZVu" - const result = did.publicKeyToDid(pubkey, "p256") - expect(result).toEqual(expectedDid) - }) - -}) - -describe("didToPublicKey", () => { - - it("handles old RSA Keys", async () => { - const toDecode = "did:key:z13V3Sog2YaUKhdGCmgx9UZuW1o1ShFJYc6DvGYe7NTt689NoL2RtpVs65Zw899YrTN9WuxdEEDm54YxWuQHQvcKfkZwa8HTgokHxGDPEmNLhvh69zUMEP4zjuARQ3T8bMUumkSLGpxNe1bfQX624ef45GhWb3S9HM3gvAJ7Qftm8iqnDQVcxwKHjmkV4hveKMTix4bTRhieVHi1oqU4QCVy4QPWpAAympuCP9dAoJFxSP6TNBLY9vPKLazsg7XcFov6UuLWsEaxJ5SomCpDx181mEgW2qTug5oQbrJwExbD9CMgXHLVDE2QgLoQMmgsrPevX57dH715NXC2uY6vo2mYCzRY4KuDRUsrkuYCkewL8q2oK1BEDVvi3Sg8pbC9QYQ5mMiHf8uxiHxTAmPedv8" - const expectedKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB" - const { publicKey, type } = did.didToPublicKey(toDecode) - expect(publicKey).toEqual(expectedKey) - expect(type).toEqual("rsa") - }) - - it("handles standardized RSA Keys", async () => { - const toDecode = "did:key:z4MXj1wBzi9jUstyNvmiK5WLRRL4rr9UvzPxhry1CudCLKWLyMbP1WoTwDfttBTpxDKf5hAJEjqNbeYx2EEvrJmSWHAu7TJRPTrE3QodbMfRvRNRDyYvaN1FSQus2ziS1rWXwAi5Gpc16bY3JwjyLCPJLfdRWHZhRXiay5FWEkfoSKy6aftnzAvqNkKBg2AxgzGMinR6d1WiH4w5mEXFtUeZkeo4uwtRTd8rD9BoVaHVkGwJkksDybE23CsBNXiNfbweFVRcwfTMhcQsTsYhUWDcSC6QE3zt9h4Rsrj7XRYdwYSK5bc1qFRsg5HULKBp2uZ1gcayiW2FqHFcMRjBieC4LnSMSD1AZB1WUncVRbPpVkn1UGhCU" - const expectedKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQAB" - const { publicKey, type } = did.didToPublicKey(toDecode) - expect(publicKey).toEqual(expectedKey) - expect(type).toEqual("rsa") - }) - - it("handles Ed25519 Keys", async () => { - const toDecode = "did:key:z6MkgYGF3thn8k1Fv4p4dWXKtsXCnLH7q9yw4QgNPULDmDKB" - const expectedKey = "Hv+AVRD2WUjUFOsSNbsmrp9fokuwrUnjBcr92f0kxw4=" - const { publicKey, type } = did.didToPublicKey(toDecode) - expect(publicKey).toEqual(expectedKey) - expect(type).toEqual("ed25519") - }) - - it("handles BLS12-381 Keys", async () => { - const toDecode = "did:key:z6HpYD1br5P4QVh5rjRGAkBfKMWes44uhKmKdJ6dN2Nm9gHK" - const expectedKey = "Hv+AVRD2WUjUFOsSNbsmrp9fokuwrUnjBcr92f0kxw4=" - const { publicKey, type } = did.didToPublicKey(toDecode) - expect(publicKey).toEqual(expectedKey) - expect(type).toEqual("bls12-381") - }) - - it("handles NIST P-256 Keys", async () => { - const toDecode = "did:key:zDnaeVHXWgKUpJFc8AUfRDuRWfsAQejmZu5HrERh41iGumZVu" - const expectedKey = "BEgg6smRlRQXKqzJHu0w5/nHcy7zYNxFXwTKUyyCOoDMztUvQn5VZg668v4MecHGUZTeHkaZhSraK7RtJuXfWp4=" - const { publicKey, type } = did.didToPublicKey(toDecode) - expect(publicKey).toEqual(expectedKey) - expect(type).toEqual("p256") - }) - -}) diff --git a/tests/ecdsa.test.ts b/tests/ecdsa.test.ts deleted file mode 100644 index 3d74917..0000000 --- a/tests/ecdsa.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import * as did from "../src/did" -import ECDSAKeyPair from "../src/keypair/ecdsa" - - -describe("ecdsa", () => { - - let p256Keypair: ECDSAKeyPair - - let p256Signature: Uint8Array - - const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) - - it("creates an ecdsa keypairs with different curves", async () => { - p256Keypair = await ECDSAKeyPair.create() - }) - - it("returns a publicKeyStr and did: curve P-256", () => { - const keyDid = p256Keypair.did() - const publicKey = p256Keypair.publicKeyStr() - const transformed = did.didToPublicKey(keyDid) - expect(transformed.publicKey).toEqual(publicKey) - expect(transformed.type).toEqual("p256") - }) - - it("signs data: curve P-256", async () => { - p256Signature = await p256Keypair.sign(data) - }) - - it("can verify signature: P-256", async () => { - const isValid = await did.verifySignature(data, p256Signature, p256Keypair.did()) - expect(isValid).toBeTruthy() - }) - -}) diff --git a/tests/ed25519.test.ts b/tests/ed25519.test.ts deleted file mode 100644 index 65769d9..0000000 --- a/tests/ed25519.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as did from "../src/did" -import EdwardsKey from "../src/keypair/ed25519" - -describe("ed25519", () => { - - let keypair: EdwardsKey - let signature: Uint8Array - const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9]) - - it("creates an edwards curve keypair", async () => { - keypair = await EdwardsKey.create() - }) - - it("returns a publicKeyStr and did", () => { - const publicKey = keypair.publicKeyStr() - const keyDid = keypair.did() - const transformed = did.didToPublicKey(keyDid) - expect(transformed.publicKey).toEqual(publicKey) - expect(transformed.type).toEqual("ed25519") - }) - - it("signs data", async () => { - signature = await keypair.sign(data) - }) - - it("can verify signature", async () => { - const isValid = await did.verifySignature(data, signature, keypair.did()) - expect(isValid).toEqual(true) - }) - -}) diff --git a/tsconfig.json b/tsconfig.json index b59f12b..c60fdc6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,8 @@ "strict": true, "moduleResolution": "node", "esModuleInterop": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "allowJs": true }, "include": [ "src/**/*" diff --git a/yarn.lock b/yarn.lock index 87c89f9..9812576 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,325 +3,157 @@ "@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: - "@jridgewell/trace-mapping" "^0.3.0" + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: - "@babel/highlight" "^7.16.7" + "@babel/highlight" "^7.18.6" -"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" - integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== - dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/compat-data@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" - integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== - -"@babel/compat-data@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.7.tgz#078d8b833fbbcc95286613be8c716cef2b519fa2" - integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ== - -"@babel/core@^7.1.0", "@babel/core@^7.7.2": - version "7.15.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.5.tgz#f8ed9ace730722544609f90c9bb49162dc3bf5b9" - integrity sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.4" - "@babel/helper-compilation-targets" "^7.15.4" - "@babel/helper-module-transforms" "^7.15.4" - "@babel/helpers" "^7.15.4" - "@babel/parser" "^7.15.5" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - source-map "^0.5.0" +"@babel/compat-data@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" + integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== -"@babel/core@^7.12.3", "@babel/core@^7.8.0": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.9.tgz#6bae81a06d95f4d0dec5bb9d74bbc1f58babdcfe" - integrity sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw== +"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.9.tgz#805461f967c77ff46c74ca0460ccf4fe933ddd59" + integrity sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g== dependencies: "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.9" - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helpers" "^7.17.9" - "@babel/parser" "^7.17.9" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.9" - "@babel/types" "^7.17.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.9" + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-module-transforms" "^7.18.9" + "@babel/helpers" "^7.18.9" + "@babel/parser" "^7.18.9" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.9" + "@babel/types" "^7.18.9" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.1" semver "^6.3.0" -"@babel/generator@^7.15.4", "@babel/generator@^7.7.2": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0" - integrity sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw== +"@babel/generator@^7.18.9", "@babel/generator@^7.7.2": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.9.tgz#68337e9ea8044d6ddc690fb29acae39359cca0a5" + integrity sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.18.9" + "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" - source-map "^0.5.0" -"@babel/generator@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.9.tgz#f4af9fd38fa8de143c29fce3f71852406fc1e2fc" - integrity sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ== +"@babel/helper-compilation-targets@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" + integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/helper-compilation-targets@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" - integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== - dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" + "@babel/compat-data" "^7.18.8" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.20.2" semver "^6.3.0" -"@babel/helper-compilation-targets@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz#a3c2924f5e5f0379b356d4cfb313d1414dc30e46" - integrity sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w== - dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" - semver "^6.3.0" - -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" - integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== - dependencies: - "@babel/helper-get-function-arity" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/helper-function-name@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" - integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/types" "^7.17.0" - -"@babel/helper-get-function-arity@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" - integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-hoist-variables@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" - integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-member-expression-to-functions@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef" - integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-module-imports@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" - integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-transforms@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz#962cc629a7f7f9a082dd62d0307fa75fe8788d7c" - integrity sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw== - dependencies: - "@babel/helper-module-imports" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-simple-access" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/helper-validator-identifier" "^7.14.9" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/helper-module-transforms@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz#3943c7f777139e7954a5355c815263741a9c1cbd" - integrity sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - -"@babel/helper-optimise-call-expression@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171" - integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-replace-supers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a" - integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/helper-simple-access@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b" - integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-simple-access@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz#aaa473de92b7987c6dfa7ce9a7d9674724823367" - integrity sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA== - dependencies: - "@babel/types" "^7.17.0" - -"@babel/helper-split-export-declaration@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257" - integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== - -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helpers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43" - integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ== - dependencies: - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/helpers@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.9.tgz#b2af120821bfbe44f9907b1826e168e819375a1a" - integrity sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.9" - "@babel/types" "^7.17.0" - -"@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== - dependencies: - "@babel/helper-validator-identifier" "^7.14.5" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.16.7": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3" - integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0" + integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A== + dependencies: + "@babel/template" "^7.18.6" + "@babel/types" "^7.18.9" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" + integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.8.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f" + integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w== + +"@babel/helper-simple-access@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" + integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-validator-identifier@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" + integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helpers@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" + integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== + dependencies: + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.15.4", "@babel/parser@^7.15.5": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549" - integrity sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q== - -"@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.9.tgz#9c94189a6062f0291418ca021077983058e171ef" - integrity sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.6", "@babel/parser@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539" + integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -408,75 +240,43 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" - integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/template@^7.15.4", "@babel/template@^7.3.3": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" - integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.15.4", "@babel/traverse@^7.7.2": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" - integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.17.3", "@babel/traverse@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.9.tgz#1f9b207435d9ae4a8ed6998b2b82300d83c37a0d" - integrity sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.9" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.9" - "@babel/types" "^7.17.0" + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz#1c09cd25795c7c2b8a4ba9ae49394576d4133285" + integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/template@^7.18.6", "@babel/template@^7.3.3": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" + integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/traverse@^7.18.9", "@babel/traverse@^7.7.2": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.9.tgz#deeff3e8f1bad9786874cb2feda7a2d77a904f98" + integrity sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.9" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.18.9" + "@babel/types" "^7.18.9" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.15.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" - integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== - dependencies: - "@babel/helper-validator-identifier" "^7.14.9" - to-fast-properties "^2.0.0" - -"@babel/types@^7.16.7", "@babel/types@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.9.tgz#7148d64ba133d8d73a41b3172ac4b83a1452205f" + integrity sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -484,19 +284,26 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@eslint/eslintrc@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6" - integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@eslint/eslintrc@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f" + integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.3.1" - globals "^13.9.0" + espree "^9.3.2" + globals "^13.15.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" - minimatch "^3.0.4" + minimatch "^3.1.2" strip-json-comments "^3.1.1" "@humanwhocodes/config-array@^0.9.2": @@ -687,17 +494,6 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^27.1.1": - version "27.1.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.1.1.tgz#77a3fc014f906c65752d12123a0134359707c0ad" - integrity sha512-yqJPDDseb0mXgKqmNqypCsb85C22K1aY5+LUxh7syIM9n/b0AsaltxNy+o6tt29VcfGDpYEve175bm3uOhcehA== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^16.0.0" - chalk "^4.0.0" - "@jest/types@^27.5.1": version "27.5.1" resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" @@ -709,20 +505,50 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/resolve-uri@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" - integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" + integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" @@ -815,10 +641,30 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": - version "7.1.16" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" - integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== + version "7.1.19" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" + integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -827,9 +673,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" - integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== dependencies: "@babel/types" "^7.0.0" @@ -842,9 +688,9 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" - integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + version "7.17.1" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.17.1.tgz#1a0e73e8c28c7e832656db372b779bfd2ef37314" + integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA== dependencies: "@babel/types" "^7.3.0" @@ -856,9 +702,9 @@ "@types/node" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "@types/istanbul-lib-report@*": version "3.0.0" @@ -875,32 +721,32 @@ "@types/istanbul-lib-report" "*" "@types/jest@^27.4.1": - version "27.4.1" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d" - integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw== + version "27.5.2" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c" + integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA== dependencies: jest-matcher-utils "^27.0.0" pretty-format "^27.0.0" "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/node@*": - version "16.9.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.2.tgz#81f5a039d6ed1941f8cc57506c74e7c2b8fc64b9" - integrity sha512-ZHty/hKoOLZvSz6BtP1g7tc7nUeJhoCf3flLjh8ZEv1vFKBWHXcnMbJMyN/pftSljNyy0kNW/UqI3DccnBnZ8w== + version "18.0.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.6.tgz#0ba49ac517ad69abe7a1508bc9b3a5483df9d5d7" + integrity sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw== "@types/node@^17.0.23": - version "17.0.23" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da" - integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/prettier@^2.1.5": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" - integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== + version "2.6.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" + integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg== "@types/stack-utils@^2.0.0": version "2.0.1" @@ -908,9 +754,9 @@ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/yargs-parser@*": - version "20.2.1" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" - integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== "@types/yargs@^16.0.0": version "16.0.4" @@ -920,89 +766,89 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz#950df411cec65f90d75d6320a03b2c98f6c3af7d" - integrity sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A== - dependencies: - "@typescript-eslint/scope-manager" "5.18.0" - "@typescript-eslint/type-utils" "5.18.0" - "@typescript-eslint/utils" "5.18.0" - debug "^4.3.2" + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.7.tgz#1621dabc1ae4084310e19e9efc80dfdbb97e7493" + integrity sha512-l4L6Do+tfeM2OK0GJsU7TUcM/1oN/N25xHm3Jb4z3OiDU4Lj8dIuxX9LpVMS9riSXQs42D1ieX7b85/r16H9Fw== + dependencies: + "@typescript-eslint/scope-manager" "5.30.7" + "@typescript-eslint/type-utils" "5.30.7" + "@typescript-eslint/utils" "5.30.7" + debug "^4.3.4" functional-red-black-tree "^1.0.1" - ignore "^5.1.8" + ignore "^5.2.0" regexpp "^3.2.0" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/parser@^5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.18.0.tgz#2bcd4ff21df33621df33e942ccb21cb897f004c6" - integrity sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ== - dependencies: - "@typescript-eslint/scope-manager" "5.18.0" - "@typescript-eslint/types" "5.18.0" - "@typescript-eslint/typescript-estree" "5.18.0" - debug "^4.3.2" - -"@typescript-eslint/scope-manager@5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz#a7d7b49b973ba8cebf2a3710eefd457ef2fb5505" - integrity sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ== - dependencies: - "@typescript-eslint/types" "5.18.0" - "@typescript-eslint/visitor-keys" "5.18.0" - -"@typescript-eslint/type-utils@5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz#62dbfc8478abf36ba94a90ddf10be3cc8e471c74" - integrity sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA== - dependencies: - "@typescript-eslint/utils" "5.18.0" - debug "^4.3.2" + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.7.tgz#99d09729392aec9e64b1de45cd63cb81a4ddd980" + integrity sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A== + dependencies: + "@typescript-eslint/scope-manager" "5.30.7" + "@typescript-eslint/types" "5.30.7" + "@typescript-eslint/typescript-estree" "5.30.7" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.30.7": + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz#8269a931ef1e5ae68b5eb80743cc515c4ffe3dd7" + integrity sha512-7BM1bwvdF1UUvt+b9smhqdc/eniOnCKxQT/kj3oXtj3LqnTWCAM0qHRHfyzCzhEfWX0zrW7KqXXeE4DlchZBKw== + dependencies: + "@typescript-eslint/types" "5.30.7" + "@typescript-eslint/visitor-keys" "5.30.7" + +"@typescript-eslint/type-utils@5.30.7": + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.7.tgz#5693dc3db6f313f302764282d614cfdbc8a9fcfd" + integrity sha512-nD5qAE2aJX/YLyKMvOU5jvJyku4QN5XBVsoTynFrjQZaDgDV6i7QHFiYCx10wvn7hFvfuqIRNBtsgaLe0DbWhw== + dependencies: + "@typescript-eslint/utils" "5.30.7" + debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.18.0.tgz#4f0425d85fdb863071680983853c59a62ce9566e" - integrity sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw== +"@typescript-eslint/types@5.30.7": + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.7.tgz#18331487cc92d0f1fb1a6f580c8ec832528079d0" + integrity sha512-ocVkETUs82+U+HowkovV6uxf1AnVRKCmDRNUBUUo46/5SQv1owC/EBFkiu4MOHeZqhKz2ktZ3kvJJ1uFqQ8QPg== -"@typescript-eslint/typescript-estree@5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz#6498e5ee69a32e82b6e18689e2f72e4060986474" - integrity sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ== +"@typescript-eslint/typescript-estree@5.30.7": + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.7.tgz#05da9f1b281985bfedcf62349847f8d168eecc07" + integrity sha512-tNslqXI1ZdmXXrHER83TJ8OTYl4epUzJC0aj2i4DMDT4iU+UqLT3EJeGQvJ17BMbm31x5scSwo3hPM0nqQ1AEA== dependencies: - "@typescript-eslint/types" "5.18.0" - "@typescript-eslint/visitor-keys" "5.18.0" - debug "^4.3.2" - globby "^11.0.4" + "@typescript-eslint/types" "5.30.7" + "@typescript-eslint/visitor-keys" "5.30.7" + debug "^4.3.4" + globby "^11.1.0" is-glob "^4.0.3" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.18.0.tgz#27fc84cf95c1a96def0aae31684cb43a37e76855" - integrity sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA== +"@typescript-eslint/utils@5.30.7": + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.7.tgz#7135be070349e9f7caa262b0ca59dc96123351bb" + integrity sha512-Z3pHdbFw+ftZiGUnm1GZhkJgVqsDL5CYW2yj+TB2mfXDFOMqtbzQi2dNJIyPqPbx9mv2kUxS1gU+r2gKlKi1rQ== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.18.0" - "@typescript-eslint/types" "5.18.0" - "@typescript-eslint/typescript-estree" "5.18.0" + "@typescript-eslint/scope-manager" "5.30.7" + "@typescript-eslint/types" "5.30.7" + "@typescript-eslint/typescript-estree" "5.30.7" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.18.0": - version "5.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz#c7c07709823804171d569017f3b031ced7253e60" - integrity sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg== +"@typescript-eslint/visitor-keys@5.30.7": + version "5.30.7" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.7.tgz#c093abae75b4fd822bfbad9fc337f38a7a14909a" + integrity sha512-KrRXf8nnjvcpxDFOKej4xkD7657+PClJs5cJVSG7NNoCNnjEdc46juNAQt7AyuWctuCgs6mVRc1xGctEqrjxWw== dependencies: - "@typescript-eslint/types" "5.18.0" - eslint-visitor-keys "^3.0.0" + "@typescript-eslint/types" "5.30.7" + eslint-visitor-keys "^3.3.0" abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== acorn-globals@^6.0.0: version "6.0.0" @@ -1012,7 +858,7 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" -acorn-jsx@^5.3.1: +acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -1022,20 +868,20 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4: - version "8.5.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" - integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== - -acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.1: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== agent-base@6: version "6.0.2" @@ -1061,7 +907,7 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.21.3" -ansi-regex@^5.0.0, ansi-regex@^5.0.1: +ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== @@ -1093,6 +939,11 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1113,7 +964,7 @@ array-union@^2.1.0: asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== babel-jest@^27.5.1: version "27.5.1" @@ -1194,7 +1045,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: +braces@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1206,27 +1057,15 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.16.6: - version "4.17.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.0.tgz#1fcd81ec75b41d6d4994fb0831b92ac18c01649c" - integrity sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g== +browserslist@^4.20.2: + version "4.21.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.2.tgz#59a400757465535954946a400b841ed37e2b4ecf" + integrity sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA== dependencies: - caniuse-lite "^1.0.30001254" - colorette "^1.3.0" - electron-to-chromium "^1.3.830" - escalade "^3.1.1" - node-releases "^1.1.75" - -browserslist@^4.17.5: - version "4.20.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88" - integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA== - dependencies: - caniuse-lite "^1.0.30001317" - electron-to-chromium "^1.4.84" - escalade "^3.1.1" - node-releases "^2.0.2" - picocolors "^1.0.0" + caniuse-lite "^1.0.30001366" + electron-to-chromium "^1.4.188" + node-releases "^2.0.6" + update-browserslist-db "^1.0.4" bs-logger@0.x: version "0.2.6" @@ -1258,19 +1097,14 @@ camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== - -caniuse-lite@^1.0.30001254: - version "1.0.30001257" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz#150aaf649a48bee531104cfeda57f92ce587f6e5" - integrity sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA== + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001317: - version "1.0.30001327" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz#c1546d7d7bb66506f0ccdad6a7d07fc6d668c858" - integrity sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w== +caniuse-lite@^1.0.30001366: + version "1.0.30001368" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001368.tgz#c5c06381c6051cd863c45021475434e81936f713" + integrity sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ== chalk@^2.0.0: version "2.4.2" @@ -1294,15 +1128,10 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -ci-info@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" - integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== - ci-info@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" - integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== + version "3.3.2" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128" + integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg== cjs-module-lexer@^1.0.0: version "1.2.2" @@ -1321,7 +1150,7 @@ cliui@^7.0.2: co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== collect-v8-coverage@^1.0.0: version "1.0.1" @@ -1345,18 +1174,13 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -1367,7 +1191,7 @@ combined-stream@^1.0.8: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" @@ -1394,6 +1218,11 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1429,17 +1258,10 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" @@ -1451,7 +1273,7 @@ decimal.js@^10.2.1: dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" @@ -1466,7 +1288,7 @@ deepmerge@^4.2.2: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== detect-newline@^3.0.0: version "3.1.0" @@ -1478,6 +1300,11 @@ diff-sequences@^27.5.1: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1499,15 +1326,10 @@ domexception@^2.0.1: dependencies: webidl-conversions "^5.0.0" -electron-to-chromium@^1.3.830: - version "1.3.841" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.841.tgz#c3088948462df0dea552877ad0902df6d0d55de0" - integrity sha512-0w3dJaRfl4A+LfbdvZaGT3JPm6TbTYKeJj8y5YWaEI9Z4WBNIshlzxL3S1msMGpuhiMZQE9cfgAV8oMib+Z4Tg== - -electron-to-chromium@^1.4.84: - version "1.4.106" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.106.tgz#e7a3bfa9d745dd9b9e597616cb17283cc349781a" - integrity sha512-ZYfpVLULm67K7CaaGP7DmjyeMY4naxsbTy+syVVxT6QHI1Ww8XbJjmr9fDckrhq44WzCrcC5kH3zGpdusxwwqg== +electron-to-chromium@^1.4.188: + version "1.4.196" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.196.tgz#e18cdc5c1c2c2ebf78da237d0c374cc3b244d4cb" + integrity sha512-uxMa/Dt7PQsLBVXwH+t6JvpHJnrsYBaxWKi/J6HE+/nBtoHENhwBoNkgkm226/Kfxeg0z1eMQLBRPPKcDH8xWA== emittery@^0.8.1: version "0.8.1" @@ -1534,7 +1356,7 @@ escalade@^3.1.1: escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: version "2.0.0" @@ -1586,22 +1408,17 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2" - integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA== - eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint@^8.12.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.12.0.tgz#c7a5bd1cfa09079aae64c9076c07eada66a46e8e" - integrity sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q== + version "8.20.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.20.0.tgz#048ac56aa18529967da8354a478be4ec0a2bc81b" + integrity sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA== dependencies: - "@eslint/eslintrc" "^1.2.1" + "@eslint/eslintrc" "^1.3.0" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" @@ -1612,14 +1429,14 @@ eslint@^8.12.0: eslint-scope "^7.1.1" eslint-utils "^3.0.0" eslint-visitor-keys "^3.3.0" - espree "^9.3.1" + espree "^9.3.2" esquery "^1.4.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" glob-parent "^6.0.1" - globals "^13.6.0" + globals "^13.15.0" ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" @@ -1628,7 +1445,7 @@ eslint@^8.12.0: json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.0.4" + minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" regexpp "^3.2.0" @@ -1637,13 +1454,13 @@ eslint@^8.12.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^9.3.1: - version "9.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" - integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== +espree@^9.3.2: + version "9.3.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" + integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== dependencies: - acorn "^8.7.0" - acorn-jsx "^5.3.1" + acorn "^8.7.1" + acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" esprima@^4.0.0, esprima@^4.0.1: @@ -1670,16 +1487,11 @@ estraverse@^4.1.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0: +estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -1703,7 +1515,7 @@ execa@^5.0.0: exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== expect@^27.5.1: version "27.5.1" @@ -1716,9 +1528,9 @@ expect@^27.5.1: jest-message-util "^27.5.1" fast-check@^2.24.0: - version "2.24.0" - resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.24.0.tgz#39f85586862108a4de6394c5196ebcf8b76b6c8b" - integrity sha512-iNXbN90lbabaCUfnW5jyXYPwMJLFYl09eJDkXA9ZoidFlBK63gNRvcKxv+8D1OJ1kIYjwBef4bO/K3qesUeWLQ== + version "2.25.0" + resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.25.0.tgz#5146601851bf3be0953bd17eb2b7d547936c6561" + integrity sha512-wRUT2KD2lAmT75WNIJIHECawoUUMHM0I5jrlLXGtGeqmPL8jl/EldUDjY1VCp6fDY8yflyfUeIOsOBrIbIiArg== dependencies: pure-rand "^5.0.1" @@ -1727,10 +1539,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -1746,7 +1558,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: version "1.13.0" @@ -1793,9 +1605,9 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + version "3.2.6" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" + integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== form-data@^3.0.0: version "3.0.1" @@ -1809,7 +1621,7 @@ form-data@^3.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2: version "2.3.2" @@ -1824,7 +1636,7 @@ function-bind@^1.1.1: functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" @@ -1860,27 +1672,15 @@ glob-parent@^6.0.1: dependencies: is-glob "^4.0.3" -glob@^7.0.5: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" @@ -1889,30 +1689,25 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.6.0, globals@^13.9.0: - version "13.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" - integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== +globals@^13.15.0: + version "13.17.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" + integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== dependencies: type-fest "^0.20.2" -globby@^11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.2.4: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== - graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -1921,7 +1716,7 @@ graceful-fs@^4.2.9: has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" @@ -1957,9 +1752,9 @@ http-proxy-agent@^4.0.1: debug "4" https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" debug "4" @@ -1976,11 +1771,6 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ignore@^5.1.4, ignore@^5.1.8: - version "5.1.9" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" - integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== - ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" @@ -1995,9 +1785,9 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: resolve-from "^4.0.0" import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -2005,12 +1795,12 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -2023,26 +1813,19 @@ inherits@2, inherits@^2.0.1, inherits@~2.0.1, inherits@~2.0.3: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-ci@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994" - integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ== - dependencies: - ci-info "^3.1.1" - -is-core-module@^2.2.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" - integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== +is-core-module@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== dependencies: has "^1.0.3" is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -2079,37 +1862,32 @@ is-stream@^2.0.0: is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -istanbul-lib-coverage@^3.2.0: +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" - integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== + version "5.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" + integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== dependencies: "@babel/core" "^7.12.3" "@babel/parser" "^7.14.7" @@ -2127,18 +1905,18 @@ istanbul-lib-report@^3.0.0: supports-color "^7.1.0" istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" - integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" source-map "^0.6.1" istanbul-reports@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -2493,19 +2271,7 @@ jest-snapshot@^27.5.1: pretty-format "^27.5.1" semver "^7.3.2" -jest-util@^27.0.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.2.0.tgz#bfccb85cfafae752257319e825a5b8d4ada470dc" - integrity sha512-T5ZJCNeFpqcLBpx+Hl9r9KoxBCUqeWlJ1Htli+vryigZVJ1vuLB9j35grEBASp4R13KFkV7jM52bBGnArpJN6A== - dependencies: - "@jest/types" "^27.1.1" - "@types/node" "*" - chalk "^4.0.0" - graceful-fs "^4.2.4" - is-ci "^3.0.0" - picomatch "^2.2.3" - -jest-util@^27.5.1: +jest-util@^27.0.0, jest-util@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9" integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== @@ -2631,16 +2397,9 @@ json-schema-traverse@^0.4.1: json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json5@2.x, json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -json5@^2.2.1: +json5@2.x, json5@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== @@ -2666,7 +2425,7 @@ levn@^0.4.1: levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -2686,7 +2445,7 @@ locate-path@^5.0.0: lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.merge@^4.6.2: version "4.6.2" @@ -2712,72 +2471,60 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: - tmpl "1.0.x" + tmpl "1.0.5" merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" -mime-db@1.49.0: - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12: - version "2.1.32" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.49.0" + mime-db "1.52.0" mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.3: +minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -2789,34 +2536,29 @@ ms@2.1.2: integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== multiformats@^9.4.2: - version "9.4.7" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.4.7.tgz#df2caa6ccd975218bbbacd69e45bb76cc2a53654" - integrity sha512-fZbcdf7LnvokPAZYkv4TLXe7PAg9sQ5qLXcwrAmZOloEb2+5FtFiAY+l3/9wsu4oTJXTV3JSggFQQ2dJLS01vA== + version "9.7.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.7.0.tgz#845799e8df70fbb6b15922500e45cb87cf12f7e5" + integrity sha512-uv/tcgwk0yN4DStopnBN4GTgvaAlYdy6KnZpuzEPFOYQd71DYFJjs0MN1ERElAflrZaYyGBWXyGxL5GgrxIx0Q== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^1.1.75: - version "1.1.75" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe" - integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw== - -node-releases@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== noms@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859" - integrity sha1-2o69nzr51nYJGbJ9nNyAkqczKFk= + integrity sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow== dependencies: inherits "^2.0.1" readable-stream "~1.0.31" @@ -2834,14 +2576,14 @@ npm-run-path@^4.0.1: path-key "^3.0.0" nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + version "2.2.1" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.1.tgz#10a9f268fbf4c461249ebcfe38e359aa36e2577c" + integrity sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg== once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -2930,14 +2672,14 @@ path-exists@^4.0.0: path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -2952,10 +2694,10 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pirates@^4.0.4: version "4.0.5" @@ -2977,19 +2719,9 @@ prelude-ls@^1.2.1: prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== -pretty-format@^27.0.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.0.tgz#ee37a94ce2a79765791a8649ae374d468c18ef19" - integrity sha512-KyJdmgBkMscLqo8A7K77omgLx5PWPiXJswtTtFV7XgVZv2+qPk6UivpXXO+5k6ZEbWIbLoKdx1pZ6ldINzbwTA== - dependencies: - "@jest/types" "^27.1.1" - ansi-regex "^5.0.0" - ansi-styles "^5.0.0" - react-is "^17.0.1" - -pretty-format@^27.5.1: +pretty-format@^27.0.0, pretty-format@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== @@ -3004,17 +2736,17 @@ process-nextick-args@~2.0.0: integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== prompts@^2.0.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61" - integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ== + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== dependencies: kleur "^3.0.3" sisteransi "^1.0.5" psl@^1.1.33: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" @@ -3039,7 +2771,7 @@ react-is@^17.0.1: readable-stream@~1.0.31: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -3067,7 +2799,7 @@ regexpp@^3.2.0: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve-cwd@^3.0.0: version "3.0.0" @@ -3092,12 +2824,13 @@ resolve.exports@^1.1.0: integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== resolve@^1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" reusify@^1.0.4: version "1.0.4" @@ -3135,10 +2868,10 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -semver@7.x, semver@^7.3.2, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== +semver@7.x, semver@^7.3.2, semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" @@ -3160,9 +2893,9 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.4.tgz#366a4684d175b9cab2081e3681fda3747b6c51d7" - integrity sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q== + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== sisteransi@^1.0.5: version "1.0.5" @@ -3174,41 +2907,35 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-support@^0.5.20, source-map-support@^0.5.6: - version "0.5.20" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" - integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== +source-map-support@^0.5.6: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@^0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stack-utils@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.4.tgz#bf967ae2813d3d2d1e1f59a4408676495c8112ab" - integrity sha512-ERg+H//lSSYlZhBIUu+wJnqg30AbyBbpZlIhcshpn7BNzpoRODZgfyr9J+8ERf3ooC6af3u7Lcl01nleau7MrA== + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== dependencies: escape-string-regexp "^2.0.0" - source-map-support "^0.5.20" string-length@^4.0.1: version "4.0.2" @@ -3219,18 +2946,18 @@ string-length@^4.0.1: strip-ansi "^6.0.0" string-width@^4.1.0, string-width@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" - integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== string_decoder@~1.1.1: version "1.1.1" @@ -3239,14 +2966,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -3297,6 +3017,11 @@ supports-hyperlinks@^2.0.0: has-flag "^4.0.0" supports-color "^7.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -3322,7 +3047,7 @@ test-exclude@^6.0.0: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== throat@^6.0.1: version "6.0.1" @@ -3337,7 +3062,7 @@ through2@^2.0.1: readable-stream "~2.3.6" xtend "~4.0.1" -tmpl@1.0.x: +tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== @@ -3345,7 +3070,7 @@ tmpl@1.0.x: to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" @@ -3371,9 +3096,9 @@ tr46@^2.1.0: punycode "^2.1.1" ts-jest@^27.1.4: - version "27.1.4" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.4.tgz#84d42cf0f4e7157a52e7c64b1492c46330943e00" - integrity sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ== + version "27.1.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.5.tgz#0ddf1b163fbaae3d5b7504a1e65c914a95cff297" + integrity sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA== dependencies: bs-logger "0.x" fast-json-stable-stringify "2.x" @@ -3384,6 +3109,25 @@ ts-jest@^27.1.4: semver "7.x" yargs-parser "20.x" +ts-node@^10.8.2: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@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" + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -3406,7 +3150,7 @@ type-check@^0.4.0, type-check@~0.4.0: type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" @@ -3433,9 +3177,9 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" typescript@^4.6.3: - version "4.6.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" - integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== uint8arrays@^3.0.0: version "3.0.0" @@ -3454,6 +3198,14 @@ untildify@^4.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== +update-browserslist-db@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" + integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3464,7 +3216,12 @@ uri-js@^4.2.2: util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== v8-compile-cache@^2.0.3: version "2.3.0" @@ -3495,11 +3252,11 @@ w3c-xmlserializer@^2.0.0: xml-name-validator "^3.0.0" walker@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: - makeerror "1.0.x" + makeerror "1.0.12" webidl-conversions@^5.0.0: version "5.0.0" @@ -3556,7 +3313,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" @@ -3569,9 +3326,9 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.4.6: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== xml-name-validator@^3.0.0: version "3.0.0" @@ -3617,6 +3374,11 @@ yargs@^16.1.0, yargs@^16.2.0: yargs-parser "^20.2.2" yarn@^1.22.18: - version "1.22.18" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.18.tgz#05b822ade8c672987bab8858635145da0850f78a" - integrity sha512-oFffv6Jp2+BTUBItzx1Z0dpikTX+raRdqupfqzeMKnoh7WD6RuPAxcqDkMUy9vafJkrB0YaV708znpuMhEBKGQ== + version "1.22.19" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.19.tgz#4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" + integrity sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==