diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..43734c896 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "javascript.format.insertSpaceBeforeFunctionParenthesis": false, + "typescript.format.insertSpaceBeforeFunctionParenthesis": false, + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/packages/access-client/package.json b/packages/access-client/package.json index 8fbd00ded..3c34a012a 100644 --- a/packages/access-client/package.json +++ b/packages/access-client/package.json @@ -13,9 +13,6 @@ "type": "module", "types": "dist/src/index.d.ts", "main": "src/index.js", - "bin": { - "w3access": "./src/cli/index.js" - }, "scripts": { "lint": "tsc --build && eslint '**/*.{js,ts}' && prettier --check '**/*.{js,ts,yml,json}' --ignore-path ../../.gitignore", "build": "tsc --build", @@ -71,18 +68,11 @@ "@web3-storage/did-mailto": "workspace:^", "bigint-mod-arith": "^3.1.2", "conf": "10.2.0", - "inquirer": "^9.1.4", - "isomorphic-ws": "^5.0.0", - "kysely": "^0.23.4", "multiformats": "^12.1.2", "one-webcrypto": "^1.0.3", - "ora": "^6.1.2", "p-defer": "^4.0.0", - "p-wait-for": "^5.0.0", "type-fest": "^3.3.0", - "uint8arrays": "^4.0.6", - "ws": "^8.12.0", - "zod": "^3.20.2" + "uint8arrays": "^4.0.6" }, "devDependencies": { "@types/assert": "^1.5.6", @@ -97,7 +87,6 @@ "hd-scripts": "^4.0.0", "mocha": "^10.2.0", "playwright-test": "^12.3.4", - "sade": "^1.8.1", "sinon": "^15.0.3", "typescript": "5.2.2", "watch": "^1.0.2" diff --git a/packages/access-client/src/agent-use-cases.js b/packages/access-client/src/agent-use-cases.js index d46fa7155..30e45dc4b 100644 --- a/packages/access-client/src/agent-use-cases.js +++ b/packages/access-client/src/agent-use-cases.js @@ -1,10 +1,9 @@ import { addSpacesFromDelegations, Agent as AccessAgent } from './agent.js' import * as Ucanto from '@ucanto/interface' import * as Access from '@web3-storage/capabilities/access' -import { bytesToDelegations, stringToDelegation } from './encoding.js' +import { bytesToDelegations } from './encoding.js' import { Provider } from '@web3-storage/capabilities' import * as w3caps from '@web3-storage/capabilities' -import { Websocket, AbortError } from './utils/ws.js' import { AgentData, isSessionProof } from './agent-data.js' import * as ucanto from '@ucanto/core' import { DID as DIDValidator } from '@ucanto/validator' @@ -130,43 +129,6 @@ export async function pollAccessClaimUntil( } } -/** - * @param {AccessAgent} access - * @param {object} [opts] - * @param {AbortSignal} [opts.signal] - * @deprecated - use waitForAuthorizationOnSocket - */ -export async function waitForDelegationOnSocket(access, opts) { - const ws = new Websocket(access.url, 'validate-ws') - await ws.open(opts) - - ws.send({ - did: access.did(), - }) - - try { - const msg = await ws.awaitMsg(opts) - - if (msg.type === 'timeout') { - await ws.close(1000, 'agent got timeout waiting for validation') - throw new Error('Email validation timed out.') - } - - if (msg.type === 'delegation') { - const delegation = stringToDelegation(msg.delegation) - await ws.close(1000, 'received delegation, agent is done with ws') - return delegation - } - } catch (error) { - if (error instanceof AbortError) { - await ws.close(1000, 'AbortError: agent failed to get delegation') - throw new TypeError('Failed to get delegation', { cause: error }) - } - throw error - } - throw new TypeError('Failed to get delegation') -} - /** * @template [T={}] * @typedef {{ signal?: AbortSignal } & T} AuthorizationWaiterOpts @@ -176,19 +138,6 @@ export async function waitForDelegationOnSocket(access, opts) { * @typedef {(accessAgent: AccessAgent, opts: AuthorizationWaiterOpts) => Promise>} AuthorizationWaiter */ -/** - * Wait for the authorization process to complete by waiting on a - * well-known websocket endpoint for the access-api server to - * receive and forward a session delegation from the authorization - * email flow. - * - * @type AuthorizationWaiter - */ -export async function waitForAuthorizationOnSocket(access, opts = {}) { - const delegation = await waitForDelegationOnSocket(access, opts) - return [delegation] -} - /** * Wait for authorization process to complete by polling executions of the * `access/claim` capability and waiting for the result to include @@ -260,24 +209,6 @@ export async function authorizeWaitAndClaim(accessAgent, email, opts) { }) } -/** - * Request authorization of a session allowing this agent to issue UCANs - * signed by the passed email address. - * - * @param {AccessAgent} access - * @param {`${string}@${string}`} email - * @param {object} [opts] - * @param {AbortSignal} [opts.signal] - * @param {Iterable<{ can: Ucanto.Ability }>} [opts.capabilities] - * @deprecated use authorizeWaitAndClaim directly going forward, passing it the expectAuthorization: waitForAuthorizationOnSocket to replicate this function's behavior - */ -export async function authorizeWithSocket(access, email, opts) { - return authorizeWaitAndClaim(access, email, { - ...opts, - expectAuthorization: waitForAuthorizationOnSocket, - }) -} - /** * Invokes voucher/redeem for the free tier, wait on the websocket for the voucher/claim and invokes it * diff --git a/packages/access-client/src/agent.js b/packages/access-client/src/agent.js index 6f2dbbfef..157eca854 100644 --- a/packages/access-client/src/agent.js +++ b/packages/access-client/src/agent.js @@ -6,7 +6,6 @@ import * as Ucanto from '@ucanto/interface' import * as CAR from '@ucanto/transport/car' import * as HTTP from '@ucanto/transport/http' import * as ucanto from '@ucanto/core' -import { Peer } from './awake/peer.js' import * as Space from '@web3-storage/capabilities/space' import * as Access from '@web3-storage/capabilities/access' @@ -562,14 +561,6 @@ export class Agent { ) } - /** - * - * @param {import('../src/awake/types').Channel} channel - */ - peer(channel) { - return new Peer({ agent: this, channel }) - } - /** * Get Space information from Access service * diff --git a/packages/access-client/src/awake/channel.js b/packages/access-client/src/awake/channel.js deleted file mode 100644 index 82031bda3..000000000 --- a/packages/access-client/src/awake/channel.js +++ /dev/null @@ -1,336 +0,0 @@ -/* eslint-disable no-console */ -import * as UCAN from '@ipld/dag-ucan' -import * as DID from '@ipld/dag-ucan/did' -import WS from 'isomorphic-ws' -import pWaitFor from 'p-wait-for' -import { concatEncode } from './encoding.js' -import * as Messages from './messages.js' - -const AWAKE_VERSION = '0.1.0' - -/** - * @template [T=unknown] - * @typedef {(event: T) => void} Handler - */ - -/** - * @template [T=unknown] - * @typedef {Array> } EventHandlerList - */ - -/** - * @template {Record} [Events=Record] - * @typedef {Map>} EventHandlerMap - */ - -/** - * @typedef {import('./types').Channel} ChannelType - * @implements {ChannelType} - */ -export class Channel { - /** @type {EventHandlerMap} */ - #subs - - /** - * @param {string | URL} host - * @param {string} topic - * @param {import('../crypto/types').KeyExchangeKeypair} keypair - */ - constructor(host, topic, keypair) { - this.url = new URL('connect/' + topic, host) - this.ws = undefined - this.keypair = keypair - this.#subs = new Map() - this.onMessage = undefined - this.attemps = 0 - /** - * @type {string | number | NodeJS.Timeout | undefined} - */ - this.timeout = undefined - this.forceClose = false - } - - async open() { - this.ws = this.connect() - await pWaitFor(() => this.ws?.readyState === 1) - return this - } - - connect() { - if (this.attemps > 10) { - return - } - - const ws = new WS(this.url) - this.ws = ws - - ws.addEventListener('close', (event) => { - if (!this.forceClose && !this.timeout) { - this.timeout = setTimeout(() => { - this.attemps++ - this.connect() - }, 1000) - console.log('WebSocket closed, reconnecting:', event.code, event.reason) - } else { - clearTimeout(this.timeout) - this.timeout = undefined - // console.log('WebSocket closed:', event.code, event.reason) - } - }) - ws.addEventListener('error', (event) => { - // console.log('WebSocket error', event) - }) - ws.addEventListener('open', (event) => { - // console.log('WebSocket open') - clearTimeout(this.timeout) - this.timeout = undefined - }) - ws.addEventListener('message', (event) => { - // @ts-ignore - const data = JSON.parse(event.data) - if (data.error) { - console.error(data.error) - } - - if (data.type) { - this.publish(data) - } - - if (this.onMessage !== undefined && data.type) { - this.onMessage(data) - } - }) - - return ws - } - - /** - * @param {number} [code] - * @param {string | Buffer } [reason] - */ - async close(code, reason) { - if (this.ws) { - this.forceClose = true - this.ws.close(code, reason) - await pWaitFor(() => this.ws?.readyState === 3) - } - return this - } - - /** - * @param {any} data - */ - send(data) { - if (this.ws?.readyState !== 1) { - throw new Error('Websocket is not active.') - } - - this.ws.send(JSON.stringify(data)) - } - - /** - * @param {import('./types').MessageType} type - * @param { Handler } fn - * @param {boolean} [once] - */ - subscribe(type, fn, once) { - let handlers = this.#subs.get(type) - let handler = fn - - if (once) { - handler = (data) => { - handlers?.splice(handlers.indexOf(handler) >>> 0, 1) - Reflect.apply(fn, this, [data]) - } - } - - if (handlers) { - handlers.push(handler) - } else { - handlers = [handler] - this.#subs.set(type, handlers) - } - - return () => { - handlers?.splice(handlers.indexOf(handler) >>> 0, 1) - } - } - - /** - * @param {import('./types').MessageType} type - * @param { Handler } fn - */ - unsubscribe(type, fn) { - const handlers = this.#subs.get(type) - if (handlers) { - if (fn) { - handlers.splice(handlers.indexOf(fn) >>> 0, 1) - } else { - this.#subs.set(type, []) - } - } - } - - /** - * @private - * @param {import('./types').AwakeMessage} data - */ - publish(data) { - const { type } = data - - const handlers = this.#subs.get(type)?.slice() - if (handlers) { - for (const h of handlers) { - h(data) - } - } - } - - /** - * @type {ChannelType['awaitInit']} - */ - awaitInit() { - return new Promise((resolve, reject) => { - this.onMessage = (/** @type {import('./types').AwakeMessage} */ msg) => { - try { - if (msg.type === 'awake/init') { - this.onMessage = undefined - console.log('receive', msg.type) - - const data = Messages.InitResponse.parse(msg) - resolve({ - awv: data.awv, - type: data.type, - did: DID.parse(data.did), - caps: /** @type {UCAN.Capabilities} */ (data.caps), - }) - } - } catch (error) { - reject(error) - } - } - }) - } - - /** - * @type {ChannelType['awaitRes']} - */ - awaitRes() { - return new Promise((resolve, reject) => { - this.onMessage = async ( - /** @type {import('./types').AwakeMessage} */ msg - ) => { - try { - if (msg.type === 'awake/res') { - this.onMessage = undefined - console.log('receive', msg.type) - - const data = Messages.ResResponse.parse(msg) - const iss = DID.parse(data.iss) - const decryptedMsg = await this.keypair.decryptFromDid( - data.msg, - iss.did() - ) - resolve({ - awv: data.awv, - type: data.type, - iss, - aud: DID.parse(data.aud), - ucan: UCAN.parse(decryptedMsg), - }) - } - } catch (error) { - reject(error) - } - } - }) - } - - /** - * - * @type {ChannelType['awaitMsg']} - */ - awaitMsg(did) { - return new Promise((resolve, reject) => { - this.onMessage = async ( - /** @type {import('./types').AwakeMsg} */ msg - ) => { - try { - if ( - msg.type === 'awake/msg' && - msg.msg && - typeof msg.msg === 'string' - ) { - this.onMessage = undefined - - msg.msg = JSON.parse( - await this.keypair.decryptFromDid(msg.msg, did.did()) - ) - console.log('receive', msg.type) - resolve(msg) - } - } catch (error) { - reject(error) - } - } - }) - } - - /** - * @type {ChannelType['sendInit']} - */ - async sendInit(caps) { - console.log('send awake/init') - this.send({ - awv: AWAKE_VERSION, - type: 'awake/init', - did: this.keypair.did, - caps, - }) - } - - /** - * @type {ChannelType['sendRes']} - */ - async sendRes(aud, ucan) { - console.log('send awake/res') - - const msg = await this.keypair.encryptForDid(UCAN.format(ucan), aud.did()) - this.send({ - awv: AWAKE_VERSION, - type: 'awake/res', - iss: this.keypair.did, - aud: aud.did(), - msg, - }) - } - - /** - * @type {ChannelType['sendMsg']} - */ - async sendMsg(did, msg) { - console.log('send awake/msg') - const id = await concatEncode([ - await this.keypair.pubkey(), - DID.encode(did), - ]) - - this.send({ - awv: AWAKE_VERSION, - type: 'awake/msg', - id, - msg: await this.keypair.encryptForDid(JSON.stringify(msg), did.did()), - }) - } - - /** - * @type {ChannelType['sendFin']} - */ - async sendFin(did) { - await this.sendMsg(did, { - 'awake/fin': 'disconnect', - }) - - await this.close() - } -} diff --git a/packages/access-client/src/awake/encoding.js b/packages/access-client/src/awake/encoding.js deleted file mode 100644 index 284bca966..000000000 --- a/packages/access-client/src/awake/encoding.js +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable unicorn/prefer-spread */ -import * as u8 from 'uint8arrays' -import { sha256 } from 'multiformats/hashes/sha2' - -/** - * - * @param {ArrayLike[]} buffers - * @param {import('uint8arrays/to-string').SupportedEncodings} [encoding] - */ -export async function concatEncode(buffers, encoding = 'base64') { - const out = await sha256.encode(u8.concat(buffers)) - - return u8.toString(out, encoding) -} diff --git a/packages/access-client/src/awake/messages.js b/packages/access-client/src/awake/messages.js deleted file mode 100644 index 948382c70..000000000 --- a/packages/access-client/src/awake/messages.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @module awake-messages - * @packageDocumentation - * @ignore - */ -import { z } from 'zod' - -export const MessageType = z.enum(['awake/init', 'awake/res', 'awake/msg']) - -export const AwakeMessage = z.object({ - awv: z.literal('0.1.0'), - type: MessageType, -}) - -export const PinChallengeMessage = z - .object({ - did: z - .string() - .startsWith('did:', { message: 'should be a DID `did:key:z...`' }), - sig: z.string(), - }) - .strict() - -export const AckMessage = z - .object({ - 'awake/ack': z - .string() - .startsWith('did:', { message: 'should be a DID `did:key:z...`' }), - }) - .strict() - -export const InitResponse = AwakeMessage.extend({ - type: z.literal('awake/init'), - did: z - .string() - .startsWith('did:', { message: 'should be a DID `did:key:z...`' }), - caps: z - .array( - z.object({ - with: z.string(), - can: z.string(), - }) - ) - .nonempty(), -}).strict() - -export const DID = z - .string() - .startsWith('did:', { message: 'should be a DID `did:key:z...`' }) - -export const ResResponse = AwakeMessage.extend({ - type: z.literal('awake/res'), - iss: DID, - aud: DID, - msg: z.string().min(1), -}).strict() diff --git a/packages/access-client/src/awake/peer.js b/packages/access-client/src/awake/peer.js deleted file mode 100644 index c96ff7016..000000000 --- a/packages/access-client/src/awake/peer.js +++ /dev/null @@ -1,206 +0,0 @@ -import * as UCAN from '@ipld/dag-ucan' -import * as DID from '@ipld/dag-ucan/did' -import * as Signature from '@ipld/dag-ucan/signature' -import { Verifier } from '@ucanto/principal/ed25519' -import { sha256 } from 'multiformats/hashes/sha2' -import * as u8 from 'uint8arrays' -import { stringToDelegations, delegationsToString } from '../encoding.js' -import * as Messages from './messages.js' - -export class Peer { - /** - * @param {{ - * channel: import('./types').Channel - * agent: import('../agent').Agent - * }} opts - */ - constructor(opts) { - this.channel = opts.channel - this.agent = opts.agent - this.did = opts.agent.did() - this.challenge = undefined - this.nextdid = undefined - this.audience = undefined - this.pin = Math.floor(Math.random() * 1_000_000) - } - - /** - * Bootstrap `awake/init`, receive `awake/res` and send challenge to Responder - * - * @param {import('@ipld/dag-ucan').Capabilities} caps - */ - async bootstrap(caps) { - // step 2 - awake/init send - this.channel.sendInit(caps) - - // step 3 - awake/res receive - const { ucan } = await this.channel.awaitRes() - - // step 4 - awake/msg send - // TODO: verify ucan, and check if proof includes caps sent previously - - const challenge = findKey(ucan.facts, 'awake/challenge') - this.nextdid = DID.parse(findKey(ucan.facts, 'awake/nextdid')) - - if (challenge === 'oob-pin') { - await this.sendPinSignature() - return this.pin.toString() - } - - // TODO: fail on unknown challenge with unknown-challenge message https://github.com/ucan-wg/awake#62-unknown-challenge-error - } - - async awaitBootstrap() { - // step 2 - awake/init receive - const msg = await this.channel.awaitInit() - this.nextdid = msg.did - - // step3 - awake/res send - const ucan = await UCAN.issue({ - issuer: this.agent.issuer, - audience: this.nextdid, - capabilities: [{ with: 'awake:', can: '*' }], - facts: [ - { 'awake/challenge': 'oob-pin' }, - // TODO: this should be rotated for the next step - { 'awake/nextdid': this.channel.keypair.did }, - ], - // TODO: proof for caps requested - }) - - await this.channel.sendRes(this.nextdid, ucan) - - // step 4 - awake/msg receive - const challengeMsg = await this.channel.awaitMsg(this.nextdid) - const { did, sig } = Messages.PinChallengeMessage.parse(challengeMsg.msg) - this.audience = DID.parse(did) - this.challenge = sig - } - - /** - * Acknowledgment for the PIN challenge - * - * @param {string} pin - */ - async ack(pin) { - if (!this.challenge || !this.nextdid || !this.audience) { - throw new Error('No challenge active.') - } - - // step 5 - awake/ack challenge confirmation and send - const sig = u8.fromString(this.challenge, 'base64') - const verifier = Verifier.parse(this.audience.did()) - const payload = u8.fromString(this.channel.keypair.did + pin) - const payloadHash = await sha256.encode(payload) - - // @ts-ignore - if (!(await verifier.verify(payloadHash, Signature.decode(sig)))) { - throw new Error( - `Challenge failed: ${pin} is not valid for the current challenge.` - ) - } - - // challenge response - await this.channel.sendMsg(this.nextdid, { - 'awake/ack': this.did, - }) - } - - async awaitAck() { - if (!this.nextdid) { - throw new Error('No session is active. await ack') - } - - const awakeMsgAck = await this.channel.awaitMsg(this.nextdid) - - const ack = Messages.AckMessage.parse(awakeMsgAck.msg) - - this.audience = DID.parse(ack['awake/ack']) - } - - /** - * - * @param {{ - * caps: import('./types').LinkRequest['msg']['caps'] - * meta: import('./types').PeerMeta - * }} opts - */ - async link(opts) { - if (!this.nextdid || !this.audience) { - throw new Error('No session is active. request link') - } - - const msg = { - type: 'link', - meta: opts.meta, - caps: opts.caps, - } - this.channel.sendMsg(this.nextdid, msg) - - /** @type {import('./types').LinkResponse} */ - const capsRsp = await this.channel.awaitMsg(this.nextdid) - const delegations = stringToDelegations(capsRsp.msg.delegation) - - await this.channel.sendFin(this.nextdid) - - await this.agent.addProof(delegations[0]) - - return { delegation: delegations[0], meta: capsRsp.msg.meta } - } - - async awaitLink() { - if (!this.nextdid || !this.audience) { - throw new Error('No challenge active.') - } - // request caps - /** @type {import('./types').LinkRequest} */ - const reqCap = await this.channel.awaitMsg(this.nextdid) - const d = await this.agent.delegate({ - abilities: ['*'], // TODO should be derived from reqCap - audience: this.audience, - expiration: Infinity, - audienceMeta: reqCap.msg.meta, - }) - this.channel.subscribe('awake/msg', (msg) => { - this.channel.close() - }) - this.channel.sendMsg(this.nextdid, { - meta: { - name: this.agent.did(), - type: 'device', - }, - delegation: delegationsToString([d]), - }) - } - - /** - * Build pin signature and send it - * - * @private - */ - async sendPinSignature() { - if (!this.nextdid) { - throw new Error('No session is active.') - } - - // Pin signature - const bytes = u8.fromString(this.nextdid.did() + this.pin.toString()) - const signed = await this.agent.issuer.sign(await sha256.encode(bytes)) - this.channel.sendMsg(this.nextdid, { - did: this.did, - sig: u8.toString(signed, 'base64'), - }) - } -} - -/** - * @param {any} arr - * @param {string} key - */ -function findKey(arr, key) { - for (const i of arr) { - if (i[key]) { - return i[key] - } - } -} diff --git a/packages/access-client/src/awake/readme.md b/packages/access-client/src/awake/readme.md deleted file mode 100644 index 98156f8dc..000000000 --- a/packages/access-client/src/awake/readme.md +++ /dev/null @@ -1,22 +0,0 @@ -# Awake - -## TODO - -- [ ] concurrent sessions -- [ ] ucan store class -- [ ] validate ucan https://github.com/ucan-wg/awake#331-validation-ucan in awake/res -- [ ] timeout on messages sent -- [ ] rotate chain keys - Double Ratchet -- [ ] error over channel and disconnect during bad handshake -- [ ] update according to latest spec - -## Notes - -- HKDF: HMAC-based Extract-and-Expand Key Derivation Function -- KDF: Key Derivation Function -- OKM: Output Key Material -- Double Ratchet Algorithm: https://signal.org/docs/specifications/doubleratchet/ - -### Session setup - -The Requestor SHOULD accept multiple concurrent connection attempts on this request DID, at least until the handshake is complete. diff --git a/packages/access-client/src/awake/types.ts b/packages/access-client/src/awake/types.ts deleted file mode 100644 index 24d0f807c..000000000 --- a/packages/access-client/src/awake/types.ts +++ /dev/null @@ -1,133 +0,0 @@ -import * as UCAN from '@ipld/dag-ucan' -import { Ability, Resource } from '@ipld/dag-ucan' -import WS from 'isomorphic-ws' -import { z } from 'zod' -import { KeyExchangeKeypair } from '../crypto/types.js' -import { Handler } from './channel.js' -import * as Messages from './messages.js' - -export interface Channel { - keypair: KeyExchangeKeypair - - ws?: WebSocket | WS - /** - * Sends a data as a message - * Data should run through JSON.stringify - */ - send: (data: unknown) => void - open: () => Promise - close: (code?: number, reason?: string) => Promise - subscribe: (type: MessageType, fn: Handler, once?: boolean) => () => void - - /** - * Send awake init message to responder - * did - The Requestor's initial (temp) ECDH P-256 - * - * @param caps - Capabilities that the Responder MUST provide - */ - sendInit: (caps: AwakeInit['caps']) => Promise - - awaitInit: () => Promise - - /** - * Send awake res message to requestor - * - * @param aud - The ECDH P-256 DID signalled by the Requestor in previous awake/init - * @param ucan - Validation UCAN to be AES-GCM-encrypted - */ - sendRes: (aud: UCAN.Principal, msg: UCAN.View) => Promise - - /** - * Awaits for awake/res msg and decrypts ucan payload from send DID - */ - awaitRes: () => Promise - - /** - * Send generic awake/msg with encrypted payload and message id - * - * @param did - DID to encrypt for - * @param msg - Message to be encrypted and sent - */ - sendMsg: (did: UCAN.Principal, msg: unknown) => Promise - - /** - * Awaits for a awake/msg and decrypts payload from sender DID - */ - awaitMsg: ( - did: UCAN.Principal - ) => Promise - - sendFin: (did: UCAN.Principal) => Promise -} - -export type MessageType = z.infer<(typeof Messages)['MessageType']> - -export type AwakeMessage = z.infer<(typeof Messages)['AwakeMessage']> - -export interface AwakeInit extends AwakeMessage { - did: UCAN.Principal - caps: UCAN.Capabilities -} - -export interface AwakeRes extends AwakeMessage { - iss: UCAN.Principal - aud: UCAN.Principal - ucan: UCAN.View -} - -/** - * Awake message with encrypted payload - */ -export interface AwakeMsg extends AwakeMessage { - id: string - msg: string -} - -/** - * Awake message with decrypted payload - */ -export interface AwakeMsgDecrypted extends AwakeMessage { - id: string - msg: any -} - -export type PinChallengeMessage = z.infer< - (typeof Messages)['PinChallengeMessage'] -> & { - did: `did:${string}` -} - -declare const Marker: unique symbol -export interface Phantom { - [Marker]?: T -} - -export type Encrypted = Out & Phantom - -export interface PeerMeta { - name: string - description?: string - url?: URL - image?: URL - type: 'device' | 'app' | 'service' -} - -export interface LinkRequest extends AwakeMsgDecrypted { - msg: { - type: 'link' - meta: PeerMeta - caps: Array<{ - can: Ability - with?: Resource - }> - } -} - -export interface LinkResponse extends AwakeMsgDecrypted { - msg: { - meta: PeerMeta - delegation: string - } -} - -export type MetaMap = Map diff --git a/packages/access-client/src/cli/cmd-create-space.js b/packages/access-client/src/cli/cmd-create-space.js deleted file mode 100644 index 8fb3243f9..000000000 --- a/packages/access-client/src/cli/cmd-create-space.js +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable unicorn/no-process-exit */ -/* eslint-disable no-console */ -import inquirer from 'inquirer' -import ora from 'ora' -import { Agent } from '../agent.js' -import { StoreConf } from '../stores/store-conf.js' -import { getService } from './utils.js' - -/** - * @param {{ profile: any; env: string }} opts - */ -export async function cmdCreateSpace(opts) { - const { url, servicePrincipal } = await getService(opts.env) - const store = new StoreConf({ profile: opts.profile }) - const data = await store.load() - - if (data) { - const spinner = ora('Registering with the service').start() - const agent = Agent.from(data, { store, url, servicePrincipal }) - - spinner.stopAndPersist() - const { email, name } = await inquirer.prompt([ - { - type: 'input', - name: 'name', - message: 'Input your a name for the new space:', - }, - { - type: 'input', - name: 'email', - default: 'hugomrdias@gmail.com', - message: 'Input your email to validate:', - }, - ]) - try { - spinner.start('Waiting for email validation...') - const space = await agent.createSpace(name) - - await agent.setCurrentSpace(space.did) - await agent.registerSpace(email) - spinner.succeed('Space has been created and register with the service.') - } catch (error) { - console.error(error) - // @ts-ignore - spinner.fail(error.message) - process.exit(1) - } - } else { - console.error('run setup command first.') - process.exit(1) - } -} diff --git a/packages/access-client/src/cli/cmd-link.js b/packages/access-client/src/cli/cmd-link.js deleted file mode 100644 index f5b541749..000000000 --- a/packages/access-client/src/cli/cmd-link.js +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable unicorn/no-process-exit */ -/* eslint-disable no-console */ -// @ts-ignore -// eslint-disable-next-line no-unused-vars -import inquirer from 'inquirer' -import pWaitFor from 'p-wait-for' -import { Agent } from '../agent.js' -import { Channel } from '../awake/channel.js' -import { EcdhKeypair } from '../crypto/p256-ecdh.js' -import { StoreConf } from '../stores/store-conf.js' -import { getService } from './utils.js' - -/** - * @param {string} channel - * @param {{ profile: string; env: string }} opts - */ -export async function cmdLink(channel, opts) { - const { url } = await getService(opts.env) - const store = new StoreConf({ profile: opts.profile }) - const data = await store.load() - - if (!data) { - console.error('run setup first') - process.exit(1) - } - - const agent = Agent.from(data, { store, url }) - - console.log('DID:', agent.did()) - let done = false - const host = new URL('ws://127.0.0.1:8788/connect') - if (channel) { - const ws = await new Channel( - host, - channel, - await EcdhKeypair.create() - ).open() - const requestor = agent.peer(ws) - const pin = await requestor.bootstrap([ - // @ts-ignore - { with: channel, can: 'identity/*' }, - ]) - - console.log(pin) - await requestor.awaitAck() - const link = await requestor.link({ - caps: [{ can: 'identity/*' }], - meta: { - name: agent.did(), - type: 'device', - }, - }) - - console.log(link) - - done = true - } else { - const ws = await new Channel( - host, - agent.did(), - await EcdhKeypair.create() - ).open() - - const responder = agent.peer(ws) - await responder.awaitBootstrap() - const { pin } = await inquirer.prompt({ - type: 'input', - name: 'pin', - message: 'Input your pin:', - }) - - await responder.ack(pin) - await responder.awaitLink() - - done = true - } - - await pWaitFor(() => done) -} diff --git a/packages/access-client/src/cli/cmd-setup.js b/packages/access-client/src/cli/cmd-setup.js deleted file mode 100644 index 8d40d6f5e..000000000 --- a/packages/access-client/src/cli/cmd-setup.js +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable no-console */ -import inquirer from 'inquirer' -import { AgentData } from '../agent-data.js' -import { StoreConf } from '../stores/store-conf.js' - -/** - * @param {{ profile: string, force: boolean }} opts - */ -export async function cmdSetup(opts) { - const store = new StoreConf({ profile: opts.profile }) - console.log('Path:', store.path) - - if (opts.force) { - await store.reset() - } - - const data = await store.load() - - if (data) { - console.log('Agent is already setup.') - } else { - const { name, type } = await inquirer.prompt([ - { - type: 'input', - name: 'name', - default: 'cli', - message: 'Input the name for this device:', - }, - { - type: 'list', - name: 'type', - default: 'device', - choices: [{ name: 'device' }, { name: 'app' }, { name: 'service' }], - message: 'Select this agent type:', - }, - ]) - await AgentData.create( - { - meta: { - name, - type, - }, - }, - { store } - ) - - console.log('Agent is ready to use.') - } -} diff --git a/packages/access-client/src/cli/cmd-whoami.js b/packages/access-client/src/cli/cmd-whoami.js deleted file mode 100644 index 94d8d46bf..000000000 --- a/packages/access-client/src/cli/cmd-whoami.js +++ /dev/null @@ -1,53 +0,0 @@ -/* eslint-disable no-console */ -import { Agent } from '../agent.js' -import { expirationToDate } from '../encoding.js' -import { StoreConf } from '../stores/store-conf.js' -import { NAME } from './config.js' - -/** - * @param {{ profile: any; env : string }} opts - */ -export async function cmdWhoami(opts) { - const store = new StoreConf({ profile: opts.profile }) - const data = await store.load() - if (data) { - const agent = Agent.from(data, { store }) - console.log('Agent', agent.issuer.did(), agent.meta) - console.log('Current Space', agent.currentSpaceWithMeta()) - console.log('\nSpaces:') - for (const space of agent.spaces) { - console.log( - `Name: ${space[1].name ?? 'none'} DID: ${space[0]} Registered: ${ - space[1].isRegistered - }` - ) - } - console.log('\nProofs:') - for (const proof of agent.proofs()) { - for (const cap of proof.capabilities) { - console.log( - `With resource: ${cap.with} can "${cap.can}" expires at ${proof.expiration}` - ) - } - } - - console.log('\nDelegations:') - for (const { meta, delegation } of agent.delegationsWithMeta()) { - console.log( - `Audience ${meta.audience?.name ?? 'unknown'} (${ - meta.audience?.type ?? 'unknown' - }):` - ) - for (const cap of delegation.capabilities) { - const expires = expirationToDate(delegation.expiration) - console.log( - `With resource: ${cap.with} can "${cap.can}" expires at ${ - expires ? expires.toISOString() : 'never' - }` - ) - } - } - } else { - console.error(`Run "${NAME} setup" first`) - } -} diff --git a/packages/access-client/src/cli/config.js b/packages/access-client/src/cli/config.js deleted file mode 100644 index c399f5615..000000000 --- a/packages/access-client/src/cli/config.js +++ /dev/null @@ -1,22 +0,0 @@ -import fs from 'fs' -import Conf from 'conf' - -export const NAME = 'w3access' -export const pkg = JSON.parse( - // eslint-disable-next-line unicorn/prefer-json-parse-buffer - fs.readFileSync(new URL('../../package.json', import.meta.url), { - encoding: 'utf8', - }) -) - -/** - * @param {string} profile - */ -export function getConfig(profile = 'main') { - const config = new Conf({ - projectName: NAME, - projectSuffix: '', - configName: profile, - }) - return config -} diff --git a/packages/access-client/src/cli/index.js b/packages/access-client/src/cli/index.js deleted file mode 100755 index 13e8d86c0..000000000 --- a/packages/access-client/src/cli/index.js +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env node -/* eslint-disable no-console */ -import fs from 'fs' -import sade from 'sade' -import { NAME, pkg } from './config.js' -import { getService, selectSpace } from './utils.js' -// @ts-ignore -// eslint-disable-next-line no-unused-vars -import { cmdCreateSpace } from './cmd-create-space.js' -import { cmdLink } from './cmd-link.js' -import { cmdSetup } from './cmd-setup.js' -import { cmdWhoami } from './cmd-whoami.js' -import { StoreConf } from '../stores/store-conf.js' -import { Agent } from '../agent.js' -import { abilitiesAsStrings } from '@web3-storage/capabilities' -import { delegationToString, stringToDelegation } from '../encoding.js' -import inquirer from 'inquirer' -import { Verifier } from '@ucanto/principal' -import path from 'path' - -const prog = sade(NAME) -prog - .version(pkg.version) - .option('-p, --profile', 'Select the config profile to use.', 'main') - .option( - '--env', - 'Environment "production", "staging", "dev" or "local"', - 'production' - ) - -prog.command('link [channel]').describe('Link.').action(cmdLink) -prog - .command('setup') - .option('--reset', 'Reset current store.', false) - .describe('Setup agent keypair.') - .action(cmdSetup) -prog.command('whoami').describe('Print config file content.').action(cmdWhoami) -prog - .command('create-space') - .describe('Create new space and register with the service.') - .action(cmdCreateSpace) - -prog - .command('space') - .describe('Space info.') - .action(async (opts) => { - const store = new StoreConf({ profile: opts.profile }) - const data = await store.load() - const { url, servicePrincipal } = await getService(opts.env) - if (data) { - const agent = Agent.from(data, { store, url, servicePrincipal }) - const space = await selectSpace(agent) - try { - const result = await agent.getSpaceInfo(space) - console.log(result) - } catch (error_) { - const error = /** @type {Error} */ (error_) - console.log('Error', error.message) - } - } else { - console.error(`Run "${NAME} setup" first`) - } - }) - -prog - .command('delegate') - .describe('Delegation capabilities.') - .option('--file', 'File to write the delegation into.') - .action(async (opts) => { - const store = new StoreConf({ profile: opts.profile }) - const data = await store.load() - const { url, servicePrincipal } = await getService(opts.env) - if (data) { - const agent = Agent.from(data, { store, url, servicePrincipal }) - const space = await selectSpace(agent) - - await agent.setCurrentSpace(space) - - const { audience, expiration, name, type, abilities } = - await inquirer.prompt([ - { - type: 'input', - name: 'audience', - message: 'Input audience DID:', - }, - { - type: 'input', - name: 'name', - message: 'Input audience name:', - }, - { - type: 'list', - name: 'type', - default: 'device', - choices: ['device', 'app', 'service'], - message: 'Input audience type:', - }, - { - type: 'number', - name: 'expiration', - message: 'Input expiration in seconds:', - }, - { - type: 'checkbox', - name: 'abilities', - message: 'Input abilities to delegate:', - choices: abilitiesAsStrings, - }, - ]) - - const delegation = await agent.delegate({ - audience: Verifier.parse(audience), - audienceMeta: { - name, - type, - }, - lifetimeInSeconds: isNaN(expiration) ? Infinity : expiration, - abilities, - }) - - const delString = delegationToString(delegation) - - if (opts.file) { - fs.writeFileSync(path.join(process.cwd(), opts.file), delString, { - encoding: 'utf8', - }) - } else { - console.log(delString) - } - } else { - console.error(`Run "${NAME} setup" first`) - } - }) - -prog - .command('import') - .describe('Import delegation.') - .option('--delegation') - .action(async (opts) => { - const store = new StoreConf({ profile: opts.profile }) - const data = await store.load() - const { url, servicePrincipal } = await getService(opts.env) - if (data) { - const agent = Agent.from(data, { store, url, servicePrincipal }) - - const del = fs.readFileSync(path.resolve(opts.delegation), { - encoding: 'utf8', - }) - - await agent.importSpaceFromDelegation(stringToDelegation(del)) - } else { - console.error(`Run "${NAME} setup" first`) - } - }) - -prog.parse(process.argv) diff --git a/packages/access-client/src/cli/utils.js b/packages/access-client/src/cli/utils.js deleted file mode 100644 index 8d079d00e..000000000 --- a/packages/access-client/src/cli/utils.js +++ /dev/null @@ -1,70 +0,0 @@ -// @ts-ignore -// eslint-disable-next-line no-unused-vars -import * as Ucanto from '@ucanto/interface' -import { DID } from '@ucanto/core' -import inquirer from 'inquirer' - -/** @type {Record} */ -const envs = { - production: 'https://up.web3.storage', - staging: 'https://staging.up.web3.storage', - dev: 'https://dev.up.web3.storage', - local: 'http://127.0.0.1:8787', -} - -/** @type {Record} */ -const dids = { - production: 'did:web:web3.storage', - staging: 'did:web:staging.web3.storage', - dev: 'did:web:dev.web3.storage', -} - -/** - * @type {import("@ucanto/interface").Principal} - */ -let audience - -/** - * @param {string} env - */ -export async function getService(env) { - const url = new URL(envs[env]) - let did - - if (audience) { - return { url, servicePrincipal: audience } - } else { - if (env === 'local') { - const rsp = await fetch(url + 'version') - const data = await rsp.json() - did = data.did - } else { - did = dids[env] - } - - // @ts-ignore - audience = DID.parse(did) - return { url, servicePrincipal: audience } - } -} - -/** - * @template {Ucanto.Signer} T - * @param {import('../agent').Agent} agent - */ -export async function selectSpace(agent) { - const choices = [] - for (const [key, value] of agent.spaces) { - choices.push({ name: value.name, value: key }) - } - const { space } = await inquirer.prompt([ - { - type: 'list', - name: 'space', - choices, - message: 'Select space:', - }, - ]) - - return space -} diff --git a/packages/access-client/src/types.ts b/packages/access-client/src/types.ts index d365a57f1..e4d2dd8c5 100644 --- a/packages/access-client/src/types.ts +++ b/packages/access-client/src/types.ts @@ -10,7 +10,6 @@ import type { Resource, ResponseDecoder, ServiceMethod, - URI, InferInvokedCapability, CapabilityParser, Match, @@ -18,7 +17,6 @@ import type { UnknownMatch, Delegation, DID, - DIDKey, Signer, SignerArchive, SigAlg, @@ -46,47 +44,17 @@ import type { import type { SetRequired } from 'type-fest' import { Driver } from './drivers/types.js' import { SpaceUnknown } from './errors.js' -import type { ColumnType, Generated, Selectable } from 'kysely' // export other types export * from '@web3-storage/capabilities/types' export * from './errors.js' -/** - * D1 Types - */ - -export interface SpaceTable { - did: DIDKey - agent: DID - email: string - product: URI - inserted_at: Generated - updated_at: ColumnType - metadata: SpaceTableMetadata | null - invocation: string - delegation: string | null -} -export type SpaceRecord = Selectable - export interface SpaceInfoResult { // space did did: DID<'key'> providers: Array> } -export interface AccountTable { - did: DID<'mailto'> - inserted_at: Generated - updated_at: ColumnType -} -export type AccountRecord = Selectable - -export interface SpaceTableMetadata { - space: SpaceMeta - agent: AgentMeta -} - /** * Access api service definition type */ diff --git a/packages/access-client/src/utils/ws.js b/packages/access-client/src/utils/ws.js deleted file mode 100644 index 7658cc0cb..000000000 --- a/packages/access-client/src/utils/ws.js +++ /dev/null @@ -1,229 +0,0 @@ -/* eslint-disable no-console */ -import WS from 'isomorphic-ws' -import pWaitFor from 'p-wait-for' - -/** - * @template [T=unknown] - * @typedef {(event: T) => void} Handler - */ - -/** - * @template [T=unknown] - * @typedef {Array> } EventHandlerList - */ - -/** - * @template {Record} [Events=Record] - * @typedef {Map>} EventHandlerMap - */ - -export class Websocket { - /** @type {EventHandlerMap} */ - #subs - - /** - * @param {URL} host - * @param {string} topic - */ - constructor(host, topic) { - this.url = new URL(topic, host) - if (host.protocol === 'http:') { - this.url.protocol = 'ws:' - } - if (host.protocol === 'https:') { - this.url.protocol = 'wss:' - } - this.ws = undefined - this.#subs = new Map() - this.attemps = 0 - this.onMessage = undefined - /** - * @type {string | number | NodeJS.Timeout | undefined} - */ - this.timeout = undefined - this.forceClose = false - } - - /** - * @param {object} [opts] - * @param {AbortSignal} [opts.signal] - */ - async open(opts) { - this.ws = this.connect() - await pWaitFor(() => opts?.signal?.aborted || this.ws?.readyState === 1) - return this - } - - connect() { - if (this.attemps > 10) { - return - } - - const ws = new WS(this.url) - this.ws = ws - - ws.addEventListener('close', (event) => { - if (!this.forceClose && !this.timeout) { - this.timeout = setTimeout(() => { - this.attemps++ - this.connect() - }, 1000) - console.log('WebSocket closed, reconnecting:', event.code, event.reason) - } else { - clearTimeout(this.timeout) - this.timeout = undefined - // console.log('WebSocket closed:', event.code, event.reason) - } - }) - ws.addEventListener('error', (event) => { - // console.log('WebSocket error', event) - }) - ws.addEventListener('open', (event) => { - // console.log('WebSocket open') - clearTimeout(this.timeout) - this.timeout = undefined - }) - ws.addEventListener('message', (event) => { - // @ts-ignore - const data = JSON.parse(event.data) - if (data.error) { - console.error(data.error) - } - - if (data.type) { - this.publish(data) - } - - if (this.onMessage !== undefined && data.type) { - this.onMessage(data) - } - }) - - return ws - } - - /** - * @param {number} [code] - * @param {string | Buffer } [reason] - */ - async close(code, reason) { - if (this.ws) { - this.forceClose = true - this.ws.close(code, reason) - await pWaitFor(() => this.ws?.readyState === 3) - } - return this - } - - /** - * @param {any} data - */ - send(data) { - if (this.ws?.readyState !== 1) { - throw new Error('Websocket is not active.') - } - - this.ws.send(JSON.stringify(data)) - } - - /** - * @param {string} type - * @param { Handler } fn - * @param {boolean} [once] - */ - subscribe(type, fn, once) { - let handlers = this.#subs.get(type) - let handler = fn - - if (once) { - handler = (data) => { - handlers?.splice(handlers.indexOf(handler) >>> 0, 1) - Reflect.apply(fn, this, [data]) - } - } - - if (handlers) { - handlers.push(handler) - } else { - handlers = [handler] - this.#subs.set(type, handlers) - } - - return () => { - handlers?.splice(handlers.indexOf(handler) >>> 0, 1) - } - } - - /** - * @param {string} type - * @param { Handler } fn - */ - unsubscribe(type, fn) { - const handlers = this.#subs.get(type) - if (handlers) { - if (fn) { - handlers.splice(handlers.indexOf(fn) >>> 0, 1) - } else { - this.#subs.set(type, []) - } - } - } - - /** - * - * @param {unknown} data - */ - publish(data) { - // @ts-ignore - const { type } = data - - const handlers = this.#subs.get(type)?.slice() - if (handlers) { - for (const h of handlers) { - h(data) - } - } - } - - /** - * - * @param {object} [opts] - * @param {AbortSignal} [opts.signal] - */ - awaitMsg(opts) { - return new Promise((resolve, reject) => { - if (opts?.signal) { - opts.signal.addEventListener('abort', () => { - this.onMessage = undefined - reject( - new AbortError('Await message cancelled.', { - cause: opts.signal?.reason, - }) - ) - }) - } - this.onMessage = (/** @type {{ type: string; }} */ msg) => { - try { - this.onMessage = undefined - resolve(msg) - } catch (error) { - reject(error) - } - } - }) - } -} - -export class AbortError extends Error { - /** - * @param {string} message - * @param {ErrorOptions} [opts] - */ - constructor(message, opts) { - super(message, opts) - this.name = 'AbortError' - this.message = message - this.code = AbortError.code - } -} -AbortError.code = 'ERR_AWAIT_MSG_CANCEL' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af6efb30e..075ae8ef5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -75,42 +75,21 @@ importers: conf: specifier: 10.2.0 version: 10.2.0 - inquirer: - specifier: ^9.1.4 - version: 9.2.11 - isomorphic-ws: - specifier: ^5.0.0 - version: 5.0.0(ws@8.14.2) - kysely: - specifier: ^0.23.4 - version: 0.23.5 multiformats: specifier: ^12.1.2 version: 12.1.2 one-webcrypto: specifier: ^1.0.3 version: 1.0.3 - ora: - specifier: ^6.1.2 - version: 6.3.1 p-defer: specifier: ^4.0.0 version: 4.0.0 - p-wait-for: - specifier: ^5.0.0 - version: 5.0.2 type-fest: specifier: ^3.3.0 version: 3.13.1 uint8arrays: specifier: ^4.0.6 version: 4.0.6 - ws: - specifier: ^8.12.0 - version: 8.14.2 - zod: - specifier: ^3.20.2 - version: 3.22.4 devDependencies: '@types/assert': specifier: ^1.5.6 @@ -148,9 +127,6 @@ importers: playwright-test: specifier: ^12.3.4 version: 12.3.8 - sade: - specifier: ^1.8.1 - version: 1.8.1 sinon: specifier: ^15.0.3 version: 15.2.0 @@ -2661,11 +2637,6 @@ packages: resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} dev: true - /@ljharb/through@2.3.9: - resolution: {integrity: sha512-yN599ZBuMPPK4tdoToLlvgJB4CLK8fGl7ntfy0Wn7U6ttNvHYurd81bfUiK/6sMkiIwm65R6ck4L6+Y3DfVbNQ==} - engines: {node: '>= 0.4'} - dev: false - /@mdx-js/mdx@1.6.22: resolution: {integrity: sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==} dependencies: @@ -3926,13 +3897,6 @@ packages: engines: {node: '>=6'} dev: true - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: false - /ansi-escapes@5.0.0: resolution: {integrity: sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==} engines: {node: '>=12'} @@ -3953,6 +3917,7 @@ packages: /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} + dev: true /ansi-sequence-parser@1.1.1: resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} @@ -4250,20 +4215,13 @@ packages: engines: {node: '>=8'} dev: true - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: false - /bl@5.1.0: resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} dependencies: buffer: 6.0.3 inherits: 2.0.4 readable-stream: 3.6.2 + dev: true /blockstore-core@3.0.0: resolution: {integrity: sha512-5ZZB5nh6kErcjZ/CTK6lCwTIGlPdkTXbD8+2xLC4Fm0WGh7g2e2lW2bfURw7mvnPtSX1xV+sN4V2ndowSgIiHQ==} @@ -4380,13 +4338,6 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: false - /buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} dependencies: @@ -4536,10 +4487,12 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + dev: true /chalk@5.3.0: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true /character-entities-legacy@1.1.4: resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} @@ -4553,10 +4506,6 @@ packages: resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} dev: true - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: false - /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -4622,22 +4571,17 @@ packages: engines: {node: '>=10'} dev: true - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: false - /cli-cursor@4.0.0: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: restore-cursor: 4.0.0 + dev: true /cli-spinners@2.9.1: resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} engines: {node: '>=6'} + dev: true /cli-table3@0.6.3: resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} @@ -4656,11 +4600,6 @@ packages: string-width: 5.1.2 dev: true - /cli-width@4.1.0: - resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} - engines: {node: '>= 12'} - dev: false - /cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} dependencies: @@ -4692,11 +4631,6 @@ packages: mimic-response: 1.0.1 dev: true - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: false - /collapse-white-space@1.0.6: resolution: {integrity: sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==} dev: true @@ -5240,12 +5174,6 @@ packages: execa: 5.1.1 dev: true - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: false - /defer-to-connect@1.1.3: resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} dev: true @@ -5726,6 +5654,7 @@ packages: /escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + dev: true /eslint-config-prettier@8.10.0(eslint@8.50.0): resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} @@ -6550,15 +6479,6 @@ packages: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: true - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: false - /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -6604,14 +6524,6 @@ packages: websocket-driver: 0.7.4 dev: true - /figures@5.0.0: - resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} - engines: {node: '>=14'} - dependencies: - escape-string-regexp: 5.0.0 - is-unicode-supported: 1.3.0 - dev: false - /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -7460,6 +7372,7 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 + dev: true /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} @@ -7549,27 +7462,6 @@ packages: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} dev: true - /inquirer@9.2.11: - resolution: {integrity: sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==} - engines: {node: '>=14.18.0'} - dependencies: - '@ljharb/through': 2.3.9 - ansi-escapes: 4.3.2 - chalk: 5.3.0 - cli-cursor: 3.1.0 - cli-width: 4.1.0 - external-editor: 3.1.0 - figures: 5.0.0 - lodash: 4.17.21 - mute-stream: 1.0.0 - ora: 5.4.1 - run-async: 3.0.0 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - dev: false - /interface-blockstore@4.0.1: resolution: {integrity: sha512-ROWKGJls7vLeFaQtI3hZVCJOkUoZ05xAi2t2qysM4d7dwVKrfm5jUOqWh8JgLL7Iup3XqJ0mKXXZuwJ3s03RSw==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -7823,14 +7715,10 @@ packages: is-path-inside: 3.0.3 dev: true - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: false - /is-interactive@2.0.0: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} + dev: true /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} @@ -7975,10 +7863,12 @@ packages: /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} + dev: true /is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} + dev: true /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} @@ -8046,14 +7936,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /isomorphic-ws@5.0.0(ws@8.14.2): - resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} - peerDependencies: - ws: '*' - dependencies: - ws: 8.14.2 - dev: false - /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} @@ -8360,11 +8242,6 @@ packages: engines: {node: '>=6'} dev: true - /kysely@0.23.5: - resolution: {integrity: sha512-TH+b56pVXQq0tsyooYLeNfV11j6ih7D50dyN8tkM0e7ndiUH28Nziojiog3qRFlmEj9XePYdZUrNJ2079Qjdow==} - engines: {node: '>=14.0.0'} - dev: false - /latest-version@5.1.0: resolution: {integrity: sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==} engines: {node: '>=8'} @@ -8547,6 +8424,7 @@ packages: dependencies: chalk: 4.1.2 is-unicode-supported: 0.1.0 + dev: true /log-symbols@5.1.0: resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} @@ -8554,6 +8432,7 @@ packages: dependencies: chalk: 5.3.0 is-unicode-supported: 1.3.0 + dev: true /log-update@5.0.1: resolution: {integrity: sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==} @@ -8903,11 +8782,6 @@ packages: resolution: {integrity: sha512-/sF3ee6zvScXMb1XFJ8gDsSnY+X8PbOyjIuBhtgis10W2Jx4ZjIhikUCIF9c4gpJxVnQIsPAFrSwTCuAjicP6g==} engines: {node: '>=8.0.0'} - /mute-stream@1.0.0: - resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: false - /nanoid@3.3.3: resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -9206,36 +9080,6 @@ packages: type-check: 0.4.0 dev: true - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.1 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: false - - /ora@6.3.1: - resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - chalk: 5.3.0 - cli-cursor: 4.0.0 - cli-spinners: 2.9.1 - is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - stdin-discarder: 0.1.0 - strip-ansi: 7.1.0 - wcwidth: 1.0.1 - dev: false - /ora@7.0.1: resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} engines: {node: '>=16'} @@ -9251,11 +9095,6 @@ packages: strip-ansi: 7.1.0 dev: true - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: false - /p-cancelable@1.1.0: resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==} engines: {node: '>=6'} @@ -9375,6 +9214,7 @@ packages: /p-timeout@6.1.2: resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} engines: {node: '>=14.16'} + dev: true /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} @@ -9385,6 +9225,7 @@ packages: engines: {node: '>=12'} dependencies: p-timeout: 6.1.2 + dev: true /package-json@6.5.0: resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==} @@ -10666,20 +10507,13 @@ packages: lowercase-keys: 1.0.1 dev: true - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: false - /restore-cursor@4.0.0: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: onetime: 5.1.2 signal-exit: 3.0.7 + dev: true /retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} @@ -10705,11 +10539,6 @@ packages: resolution: {integrity: sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ==} dev: true - /run-async@3.0.0: - resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} - engines: {node: '>=0.12.0'} - dev: false - /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -10720,6 +10549,7 @@ packages: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: tslib: 2.6.2 + dev: true /sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} @@ -11003,6 +10833,7 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -11209,6 +11040,7 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: bl: 5.1.0 + dev: true /stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} @@ -11333,6 +11165,7 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 + dev: true /strip-bom-string@1.0.0: resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} @@ -11399,6 +11232,7 @@ packages: engines: {node: '>=8'} dependencies: has-flag: 4.0.0 + dev: true /supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} @@ -11518,13 +11352,6 @@ packages: resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} dev: true - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: false - /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -11589,6 +11416,7 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true /tsutils-etc@1.4.2(tsutils@3.21.0)(typescript@4.9.5): resolution: {integrity: sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==} @@ -11640,11 +11468,6 @@ packages: engines: {node: '>=10'} dev: true - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: false - /type-fest@0.3.1: resolution: {integrity: sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==} engines: {node: '>=6'} @@ -12101,12 +11924,6 @@ packages: minimalistic-assert: 1.0.1 dev: true - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: false - /web-encoding@1.1.5: resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} dependencies: @@ -12394,15 +12211,6 @@ packages: resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} dev: true - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: false - /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -12457,6 +12265,7 @@ packages: optional: true utf-8-validate: optional: true + dev: true /xdg-basedir@4.0.0: resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} @@ -12542,10 +12351,6 @@ packages: engines: {node: '>=10'} dev: true - /zod@3.22.4: - resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} - dev: false - /zwitch@1.0.5: resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} dev: true