diff --git a/package.json b/package.json index 341d460fb..280963c1e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "packages/sdk-react-ui", "packages/sdk-ui", "packages/sdk-lab", + "packages/sdk-analytics", "packages/devsocket", "packages/devreact", "packages/devexpo", diff --git a/packages/sdk-analytics/README.md b/packages/sdk-analytics/README.md new file mode 100644 index 000000000..1bb9503d4 --- /dev/null +++ b/packages/sdk-analytics/README.md @@ -0,0 +1,39 @@ +# MetaMask SDK Analytics + +## Overview + +The `@metamask/sdk-analytics` package tracks analytics events for dApps using the MetaMask SDK. It provides a TypeScript-based client for sending events to an analytics API with batching and schema validation. + +## Purpose + +Enables dApps to: + +- Track SDK events (e.g., sdk_initialized, connection_initiated). +- Send events to an analytics API. +- Ensure type safety with OpenAPI schemas. + +## Features + +- Event Tracking: Supports events like sdk_initialized, sdk_used_chain, and wallet actions. +- Batching: Events are batched for efficient network usage. +- Error Handling: Uses exponential backoff for failed requests. +- Type Safety: Leverages TypeScript and OpenAPI schemas. + +## Usage + +Import the global client, enable it, set global props and track events. + +```typescript +import { analytics } from '@metamask/sdk-analytics'; + +analytics.enable(); + +analytics.setGlobalProperty('sdk_version', '1.0.0'); +analytics.setGlobalProperty('platform', 'web-desktop'); + +analytics.track('sdk_initialized', { + dapp_id: 'example.com', + anon_id: 'bbbc1727-8b85-433a-a26a-e9df70ddc81c', + integration_type: 'direct', +}); +``` diff --git a/packages/sdk-analytics/eslint.config.js b/packages/sdk-analytics/eslint.config.js new file mode 100644 index 000000000..4403dff99 --- /dev/null +++ b/packages/sdk-analytics/eslint.config.js @@ -0,0 +1,28 @@ +const tseslint = require('@typescript-eslint/eslint-plugin'); +const tsParser = require('@typescript-eslint/parser'); + +module.exports = [ + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2021, + sourceType: 'module', + }, + }, + plugins: { + '@typescript-eslint': tseslint, + }, + rules: { + ...tseslint.configs['recommended'].rules, + 'indent': ['error', 2], + 'linebreak-style': ['error', 'unix'], + 'quotes': ['error', 'single'], + 'semi': ['error', 'always'], + }, + }, + { + ignores: ['src/schema.ts', 'dist/**', 'node_modules/**'], + }, +]; \ No newline at end of file diff --git a/packages/sdk-analytics/package.json b/packages/sdk-analytics/package.json new file mode 100644 index 000000000..6cf921fa9 --- /dev/null +++ b/packages/sdk-analytics/package.json @@ -0,0 +1,27 @@ +{ + "name": "@metamask/sdk-analytics", + "version": "0.0.1", + "description": "Analytics package for MetaMask SDK", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc --build", + "lint": "eslint . --ext .ts,.tsx", + "lint:fix": "eslint . --ext .ts,.tsx --fix", + "test": "vitest", + "test:ci": "vitest --run" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^8.31.0", + "@typescript-eslint/parser": "^8.31.0", + "eslint": "^9.25.1", + "nock": "^14.0.4", + "typescript": "^5.8.3", + "vitest": "^3.1.2" + }, + "private": true, + "license": "MIT", + "dependencies": { + "openapi-fetch": "^0.13.5" + } +} diff --git a/packages/sdk-analytics/src/analytics.test.ts b/packages/sdk-analytics/src/analytics.test.ts new file mode 100644 index 000000000..52be494ec --- /dev/null +++ b/packages/sdk-analytics/src/analytics.test.ts @@ -0,0 +1,70 @@ +import * as t from 'vitest'; +import Analytics from './analytics'; +import nock from 'nock'; +import * as schema from './schema'; + +t.describe('Analytics Integration', () => { + let analytics: Analytics; + let scope: nock.Scope; + + const event: schema.components['schemas']['SdkInitializedEvent'] = { + name: 'sdk_initialized', + sdk_version: '1.0.0', + dapp_id: 'aave.com', + anon_id: 'bbbc1727-8b85-433a-a26a-e9df70ddc81c', + platform: 'web-desktop', + integration_type: 'direct', + }; + + t.afterAll(() => { + nock.cleanAll(); + }); + + t.it('should do nothing when disabled', async () => { + let captured: Event[] = []; + scope = nock('http://127.0.0.1') + .post('/v1/events', (body) => { + captured = body; // Capture the request body directly + return true; // Accept any body to proceed with the intercept + }) + .optionally() + .reply(200, { status: 'success' }, { 'Content-Type': 'application/json' }); + + analytics = new Analytics('http://127.0.0.1'); + analytics.track(event.name, { ...event }); + + // Wait for the Sender to flush the event (baseIntervalMs = 200ms + buffer) + await new Promise((resolve) => setTimeout(resolve, 300)); + + // Verify the captured payload + t.expect(captured).toEqual([]); + + scope.done(); + }); + + t.it('should track an event when enabled', async () => { + let captured: Event[] = []; + scope = nock('http://127.0.0.2') + .post('/v1/events', (body) => { + captured = body; // Capture the request body directly + return true; // Accept any body to proceed with the intercept + }) + .reply(200, { status: 'success' }, { 'Content-Type': 'application/json' }); + + analytics = new Analytics('http://127.0.0.2'); + analytics.enable(); + analytics.setGlobalProperty('sdk_version', event.sdk_version); + analytics.setGlobalProperty('anon_id', event.anon_id); + analytics.setGlobalProperty('platform', event.platform); + analytics.setGlobalProperty('integration_type', event.integration_type); + analytics.track(event.name, { dapp_id: 'some-non-global-property' }); + + // Wait for the Sender to flush the event (baseIntervalMs = 200ms + buffer) + await new Promise((resolve) => setTimeout(resolve, 300)); + + // Verify the captured payload + t.expect(captured).toEqual([{ ...event, dapp_id: 'some-non-global-property' }]); + + scope.done(); + }); +}); \ No newline at end of file diff --git a/packages/sdk-analytics/src/analytics.ts b/packages/sdk-analytics/src/analytics.ts new file mode 100644 index 000000000..1d91bcd19 --- /dev/null +++ b/packages/sdk-analytics/src/analytics.ts @@ -0,0 +1,48 @@ +import createClient from 'openapi-fetch'; +import * as schema from './schema'; +import Sender from './sender'; + +type Event = schema.components['schemas']['Event']; + +class Analytics { + private enabled: boolean = false; + private sender: Sender; + private properties: Record = {}; + + constructor(baseUrl: string) { + const client = createClient({ baseUrl }); + + const sendFn = async (batch: Event[]) => { + const res = await client.POST('/v1/events', { body: batch }); + if (res.response.status !== 200) { + throw new Error(res.error); + } + }; + + this.sender = new Sender({ batchSize: 100, baseIntervalMs: 200, sendFn }); + } + + public enable() { + if (this.enabled) return; + this.enabled = true; + this.sender.start(); + } + + public setGlobalProperty(key: string, value: string) { + this.properties[key] = value; + } + + public track(name: T['name'], properties: Partial) { + if (!this.enabled) return; + + const event: Event = { + name: name, + ...this.properties, + ...properties, + } as T; + + this.sender.enqueue(event); + } +} + +export default Analytics; diff --git a/packages/sdk-analytics/src/index.ts b/packages/sdk-analytics/src/index.ts new file mode 100644 index 000000000..9f98ff955 --- /dev/null +++ b/packages/sdk-analytics/src/index.ts @@ -0,0 +1,7 @@ +import Analytics from './analytics'; + +const client = new Analytics('https://mm-sdk-analytics.api.cx.metamask.io/'); + +export const analytics = client; // FIXME: use default export + +export default client; diff --git a/packages/sdk-analytics/src/schema.ts b/packages/sdk-analytics/src/schema.ts new file mode 100644 index 000000000..3571a88fe --- /dev/null +++ b/packages/sdk-analytics/src/schema.ts @@ -0,0 +1,432 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/v1/events": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Track events + * @description Endpoint to submit analytics events for the MetaMask SDK (version 1). + */ + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["Event"][]; + }; + }; + responses: { + /** @description Events tracked successfully */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** + * @description Indicates the success of the event tracking. + * @example success + */ + status?: string; + }; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + /** @description A union of all possible event types, differentiated by the 'name' property. */ + Event: components["schemas"]["SdkInitializedEvent"] | components["schemas"]["SdkUsedChainEvent"] | components["schemas"]["SdkConnectionInitiatedEvent"] | components["schemas"]["SdkConnectionEstablishedEvent"] | components["schemas"]["SdkConnectionRejectedEvent"] | components["schemas"]["SdkConnectionFailedEvent"] | components["schemas"]["WalletConnectionRequestReceivedEvent"] | components["schemas"]["WalletConnectionUserApprovedEvent"] | components["schemas"]["WalletConnectionUserRejectedEvent"] | components["schemas"]["SdkActionRequestedEvent"] | components["schemas"]["SdkActionSucceededEvent"] | components["schemas"]["SdkActionFailedEvent"] | components["schemas"]["SdkActionRejectedEvent"] | components["schemas"]["WalletActionReceivedEvent"] | components["schemas"]["WalletActionUserApprovedEvent"] | components["schemas"]["WalletActionUserRejectedEvent"]; + SdkInitializedEvent: { + /** + * @description Identifies the event as SDK initialization. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_initialized"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkUsedChainEvent: { + /** + * @description Identifies the event as SDK chain usage. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_used_chain"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** @description CAIP-2 chain ID used by the SDK. */ + caip_chain_id: string; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkConnectionInitiatedEvent: { + /** + * @description Identifies the event as connection initiation. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_connection_initiated"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Type of transport used for the connection. + * @enum {string} + */ + transport_type: "direct" | "websocket" | "deeplink"; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkConnectionEstablishedEvent: { + /** + * @description Identifies the event as connection established. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_connection_established"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Type of transport used for the connection. + * @enum {string} + */ + transport_type: "direct" | "websocket" | "deeplink"; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkConnectionRejectedEvent: { + /** + * @description Identifies the event as connection rejected. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_connection_rejected"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Type of transport used for the connection. + * @enum {string} + */ + transport_type: "direct" | "websocket" | "deeplink"; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkConnectionFailedEvent: { + /** + * @description Identifies the event as connection failed. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_connection_failed"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Type of transport used for the connection. + * @enum {string} + */ + transport_type: "direct" | "websocket" | "deeplink"; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + WalletConnectionRequestReceivedEvent: { + /** + * @description Identifies the event as connection request received. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "wallet_connection_request_received"; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Platform receiving the connection request. + * @enum {string} + */ + platform: "extension" | "mobile"; + }; + WalletConnectionUserApprovedEvent: { + /** + * @description Identifies the event as user-approved connection. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "wallet_connection_user_approved"; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Platform where the approval occurred. + * @enum {string} + */ + platform: "extension" | "mobile"; + }; + WalletConnectionUserRejectedEvent: { + /** + * @description Identifies the event as user-rejected connection. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "wallet_connection_user_rejected"; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Platform where the rejection occurred. + * @enum {string} + */ + platform: "extension" | "mobile"; + }; + SdkActionRequestedEvent: { + /** + * @description Identifies the event as a wallet action request. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_action_requested"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** @description The specific wallet action requested. */ + action: string; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkActionSucceededEvent: { + /** + * @description Identifies the event as a successful wallet action. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_action_succeeded"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** @description The specific wallet action that succeeded. */ + action: string; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkActionFailedEvent: { + /** + * @description Identifies the event as a failed wallet action. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_action_failed"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** @description The specific wallet action that failed. */ + action: string; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + SdkActionRejectedEvent: { + /** + * @description Identifies the event as a rejected wallet action. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "sdk_action_rejected"; + /** @description Version of the SDK. */ + sdk_version: string; + /** @description Unique identifier for the dApp. */ + dapp_id: string; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** @description The specific wallet action that was rejected. */ + action: string; + /** + * @description Platform on which the SDK is running. + * @enum {string} + */ + platform: "web-desktop" | "web-mobile" | "nodejs" | "in-app-browser" | "react-native"; + /** @description Type of integration used by the SDK. */ + integration_type: string; + }; + WalletActionReceivedEvent: { + /** + * @description Identifies the event as a received wallet action. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "wallet_action_received"; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Platform receiving the wallet action. + * @enum {string} + */ + platform: "extension" | "mobile"; + }; + WalletActionUserApprovedEvent: { + /** + * @description Identifies the event as an approved wallet action. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "wallet_action_user_approved"; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Platform where the approval occurred. + * @enum {string} + */ + platform: "extension" | "mobile"; + }; + WalletActionUserRejectedEvent: { + /** + * @description Identifies the event as a rejected wallet action. (enum property replaced by openapi-typescript) + * @enum {string} + */ + name: "wallet_action_user_rejected"; + /** + * Format: uuid + * @description Anonymous identifier for the user or session. + */ + anon_id: string; + /** + * @description Platform where the rejection occurred. + * @enum {string} + */ + platform: "extension" | "mobile"; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export type operations = Record; diff --git a/packages/sdk-analytics/src/sender.test.ts b/packages/sdk-analytics/src/sender.test.ts new file mode 100644 index 000000000..e52c585a3 --- /dev/null +++ b/packages/sdk-analytics/src/sender.test.ts @@ -0,0 +1,83 @@ +import * as t from 'vitest'; +import Sender from './sender'; + +t.describe('Sender', () => { + let sendFn: t.Mock<() => Promise>; + let sender: Sender; + + t.beforeEach(() => { + sendFn = t.vi.fn().mockResolvedValue(undefined); + sender = new Sender({ batchSize: 2, baseIntervalMs: 50, sendFn }); + }); + + t.afterEach(() => { + t.vi.clearAllMocks(); + }); + + t.it('should flush when batch size is reached', async () => { + sender.start(); + sender.enqueue('event1'); + sender.enqueue('event2'); + t.expect(sendFn).toHaveBeenCalledWith(['event1', 'event2']); // Flush at batchSize + }); + + t.it('should flush periodically', async () => { + sender.start(); + sender.enqueue('event1'); + await new Promise(resolve => setTimeout(resolve, 100)); + t.expect(sendFn).toHaveBeenCalledWith(['event1']); + }); + + t.it('should handle failure and reset interval after successful send', async () => { + let sendCount = 0; + sendFn = t.vi.fn().mockImplementation(() => { + sendCount++; + return sendCount === 1 ? Promise.reject(new Error('Failed')) : Promise.resolve(); + }); + sender = new Sender({ batchSize: 100, baseIntervalMs: 50, sendFn }); // Short interval + sender.start(); + + sender.enqueue('event1'); + t.expect(sendFn).toHaveBeenCalledTimes(0); + + // Wait for initial send + await new Promise(resolve => setTimeout(resolve, 51)); + t.expect(sendFn).toHaveBeenCalledTimes(1); + + // Wait for first attempt + retry + await new Promise(resolve => setTimeout(resolve, 101)); + t.expect(sendFn).toHaveBeenCalledTimes(2); // First attempt fails, then succeeds + + // Wait for next scheduled send (should happen at original interval) + sender.enqueue('event2'); + await new Promise(resolve => setTimeout(resolve, 51)); + t.expect(sendFn).toHaveBeenCalledTimes(3); + t.expect(sendFn).toHaveBeenCalledWith(['event2']); + }); + + t.it('should not send when batch is empty', async () => { + sender.start(); + await new Promise(resolve => setTimeout(resolve, 51)); + t.expect(sendFn).not.toHaveBeenCalled(); // No send if batch is empty + }); + + t.it('should handle concurrent sends properly', async () => { + let resolveSend: (value?: unknown) => void; + sendFn = t.vi.fn().mockImplementation(() => new Promise(resolve => { resolveSend = resolve; })); + sender = new Sender({ batchSize: 100, baseIntervalMs: 1000, sendFn }); + sender.start(); + + sender.enqueue('event1'); + await new Promise(resolve => setTimeout(resolve, 1000)); + t.expect(sendFn).toHaveBeenCalledWith(['event1']); + + sender.enqueue('event2'); // Enqueue while sending + resolveSend!(); // Finish the first send + await Promise.resolve(); // Allow async flush to complete + + // Wait for next scheduled send + await new Promise(resolve => setTimeout(resolve, 1000)); + t.expect(sendFn).toHaveBeenCalledWith(['event2']); + t.expect(sendFn).toHaveBeenCalledTimes(2); + }); +}); \ No newline at end of file diff --git a/packages/sdk-analytics/src/sender.ts b/packages/sdk-analytics/src/sender.ts new file mode 100644 index 000000000..501ee954f --- /dev/null +++ b/packages/sdk-analytics/src/sender.ts @@ -0,0 +1,73 @@ +type SenderOptions = { + batchSize: number; + baseIntervalMs: number; + sendFn: (batch: T[]) => Promise; +}; + +/** + * Sender is a class that sends batches of events to the server in an interval. + * It also uses exponential backoff to handle errors. + */ +class Sender { + private sendFn: (batch: T[]) => Promise; + + private batch: T[] = []; + + private batchSize: number; + private baseIntervalMs: number; + private currentIntervalMs: number; + private maxIntervalMs: number = 30_000; // 30 seconds + + private intervalId: NodeJS.Timeout | null = null; + + private isSending: boolean = false; + + constructor(options: SenderOptions) { + this.batchSize = options.batchSize; + this.baseIntervalMs = options.baseIntervalMs; + this.currentIntervalMs = options.baseIntervalMs; + this.sendFn = options.sendFn; + } + + public enqueue(item: T) { + this.batch.push(item); + if (this.batch.length >= this.batchSize && !this.isSending) { + this.flush(); + } + } + + public start() { + if (this.intervalId) return; + this.scheduleNextSend(); + } + + private scheduleNextSend() { + if (this.intervalId) { + clearTimeout(this.intervalId); + } + this.intervalId = setTimeout(() => this.flush(), this.currentIntervalMs); + } + + private async flush() { + if (this.isSending || this.batch.length === 0) return; + + this.isSending = true; + + const current = [...this.batch]; + + this.batch = []; + + try { + await this.sendFn(current); + this.currentIntervalMs = this.baseIntervalMs; // reset on success + } catch { + this.batch = [...current, ...this.batch]; + this.currentIntervalMs = Math.min(this.currentIntervalMs * 2, this.maxIntervalMs); // exponential backoff on error + } finally { + this.isSending = false; + this.scheduleNextSend(); + } + } +} + +export default Sender; diff --git a/packages/sdk-analytics/tsconfig.json b/packages/sdk-analytics/tsconfig.json new file mode 100644 index 000000000..9f02a8e21 --- /dev/null +++ b/packages/sdk-analytics/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "sourceMap": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] + } \ No newline at end of file diff --git a/packages/sdk-communication-layer/package.json b/packages/sdk-communication-layer/package.json index d5db912e5..dd1b4391e 100644 --- a/packages/sdk-communication-layer/package.json +++ b/packages/sdk-communication-layer/package.json @@ -46,6 +46,7 @@ "watch": "rollup -c --bundleConfigAsCjs -w" }, "dependencies": { + "@metamask/sdk-analytics": "workspace:*", "bufferutil": "^4.0.8", "date-fns": "^2.29.3", "debug": "^4.3.4", diff --git a/packages/sdk-communication-layer/src/RemoteCommunication.ts b/packages/sdk-communication-layer/src/RemoteCommunication.ts index c3259fb81..01c1962ca 100644 --- a/packages/sdk-communication-layer/src/RemoteCommunication.ts +++ b/packages/sdk-communication-layer/src/RemoteCommunication.ts @@ -1,3 +1,4 @@ +import { analytics as analyticsV2 } from '@metamask/sdk-analytics'; import debug from 'debug'; import { EventEmitter2 } from 'eventemitter2'; import packageJson from '../package.json'; @@ -294,8 +295,26 @@ export class RemoteCommunication extends EventEmitter2 { }); } - sendMessage(message: CommunicationLayerMessage): Promise { - return sendMessage(this, message); + async sendMessage(message: CommunicationLayerMessage): Promise { + if (this.state.isOriginator && message.method) { + analyticsV2.track('sdk_action_requested', { action: message.method }); + } + + try { + const ok = await sendMessage(this, message); + + // FIXME: this is in the wrong place + if (this.state.isOriginator && message.method) { + analyticsV2.track('sdk_action_succeeded', { action: message.method }); + } + + return ok; + } catch (error) { + if (this.state.isOriginator && message.method) { + analyticsV2.track('sdk_action_failed', { action: message.method }); + } + throw error; + } } async testStorage() { diff --git a/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/connectToChannel.ts b/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/connectToChannel.ts index 13aea773d..f2cd3fd28 100644 --- a/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/connectToChannel.ts +++ b/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/connectToChannel.ts @@ -1,4 +1,5 @@ // packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/connectToChannel.ts +import { analytics } from '@metamask/sdk-analytics'; import { validate } from 'uuid'; import { logger } from '../../../utils/logger'; import { RemoteCommunicationState } from '../../../RemoteCommunication'; @@ -56,4 +57,10 @@ export async function connectToChannel({ }; state.channelConfig = newChannelConfig; state.storageManager?.persistChannelConfig(newChannelConfig); + + if (!state.isOriginator) { + analytics.track('wallet_connection_user_approved', { + anon_id: state.originatorInfo?.anonId, + }); + } } diff --git a/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts b/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts index f103134ba..431148877 100644 --- a/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts +++ b/packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/rejectChannel.ts @@ -1,4 +1,5 @@ // packages/sdk-communication-layer/src/services/RemoteCommunication/ConnectionManager/connectToChannel.ts +import { analytics } from '@metamask/sdk-analytics'; import { validate } from 'uuid'; import { RemoteCommunicationState } from '../../../RemoteCommunication'; import { EventType } from '../../../types/EventType'; @@ -61,6 +62,10 @@ export async function rejectChannel({ console.error(`rejectChannel:: Error emitting analytics event`, error); }); + analytics.track('wallet_connection_user_rejected', { + anon_id: state.originatorInfo?.anonId, + }); + // emit reject event await new Promise((resolve, reject) => { socket?.emit( diff --git a/packages/sdk-communication-layer/src/services/RemoteCommunication/EventListeners/handleClientsConnectedEvent.ts b/packages/sdk-communication-layer/src/services/RemoteCommunication/EventListeners/handleClientsConnectedEvent.ts index 5c6f60afc..9c915b735 100644 --- a/packages/sdk-communication-layer/src/services/RemoteCommunication/EventListeners/handleClientsConnectedEvent.ts +++ b/packages/sdk-communication-layer/src/services/RemoteCommunication/EventListeners/handleClientsConnectedEvent.ts @@ -1,3 +1,4 @@ +import { analytics } from '@metamask/sdk-analytics'; import { logger } from '../../../utils/logger'; import packageJson from '../../../../package.json'; import { SendAnalytics } from '../../../Analytics'; @@ -52,6 +53,12 @@ export function handleClientsConnectedEvent( }); } + if (state.isOriginator) { + analytics.track('sdk_connection_established', { + transport_type: 'websocket', + }); + } + state.clientsConnected = true; state.originatorInfoSent = false; // Always re-send originator info. instance.emit(EventType.CLIENTS_CONNECTED); diff --git a/packages/sdk-communication-layer/src/services/SocketService/EventListeners/handleChannelRejected.ts b/packages/sdk-communication-layer/src/services/SocketService/EventListeners/handleChannelRejected.ts index cd9b4f367..9ef2d98e1 100644 --- a/packages/sdk-communication-layer/src/services/SocketService/EventListeners/handleChannelRejected.ts +++ b/packages/sdk-communication-layer/src/services/SocketService/EventListeners/handleChannelRejected.ts @@ -1,3 +1,4 @@ +import { analytics } from '@metamask/sdk-analytics'; import { SendAnalytics } from '../../../Analytics'; import { SocketService } from '../../../SocketService'; import { ConnectionStatus } from '../../../types/ConnectionStatus'; @@ -51,6 +52,10 @@ export function handleChannelRejected( ); }); + analytics.track('sdk_connection_rejected', { + transport_type: 'websocket', + }); + // Terminate the channel await instance.remote.disconnect({ terminate: true }); instance.remote.emit(EventType.REJECTED, { channelId }); diff --git a/packages/sdk-communication-layer/src/types/OriginatorInfo.ts b/packages/sdk-communication-layer/src/types/OriginatorInfo.ts index a9adb0414..116b34cc3 100644 --- a/packages/sdk-communication-layer/src/types/OriginatorInfo.ts +++ b/packages/sdk-communication-layer/src/types/OriginatorInfo.ts @@ -8,4 +8,5 @@ export interface OriginatorInfo { source?: string; apiVersion?: string; connector?: string; + anonId?: string; // FIXME: make this required } diff --git a/packages/sdk/package.json b/packages/sdk/package.json index f0d9436b8..c9574125d 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -51,6 +51,7 @@ "@babel/runtime": "^7.26.0", "@metamask/onboarding": "^1.0.1", "@metamask/providers": "16.1.0", + "@metamask/sdk-analytics": "workspace:*", "@metamask/sdk-communication-layer": "workspace:*", "@metamask/sdk-install-modal-web": "workspace:*", "@paulmillr/qr": "^0.2.1", diff --git a/packages/sdk/rollup.config.js b/packages/sdk/rollup.config.js index d97b8d299..9ddf15c54 100644 --- a/packages/sdk/rollup.config.js +++ b/packages/sdk/rollup.config.js @@ -28,7 +28,7 @@ const bundledDeps = [ ]; // Shared dependencies that should be deduplicated -const sharedDeps = ['eventemitter2', 'socket.io-client', 'debug', 'uuid', 'cross-fetch']; +const sharedDeps = ['eventemitter2', 'socket.io-client', 'debug', 'uuid', 'cross-fetch', '@metamask/sdk-analytics']; // Filter function to exclude bundled dependencies diff --git a/packages/sdk/src/sdk.ts b/packages/sdk/src/sdk.ts index 9617931af..d1f1045c0 100644 --- a/packages/sdk/src/sdk.ts +++ b/packages/sdk/src/sdk.ts @@ -1,3 +1,4 @@ +import { v4 as uuidv4 } from 'uuid'; import { MetaMaskInpageProvider } from '@metamask/providers'; import { CommunicationLayerPreference, @@ -205,6 +206,10 @@ export class MetaMaskSDK extends EventEmitter2 { public availableLanguages: string[] = ['en']; + private _anonId: string | undefined; + + private readonly ANON_ID_STORAGE_KEY = 'mm-sdk-anon-id'; + constructor( options: MetaMaskSDKOptions = { storage: { @@ -398,6 +403,89 @@ export class MetaMaskSDK extends EventEmitter2 { return packageJson.version; } + getDappId() { + if ( + typeof window === 'undefined' || + typeof window.location === 'undefined' + ) { + return ( + this.options.dappMetadata?.name ?? + this.options.dappMetadata?.url ?? + 'N/A' + ); + } + + return window.location.hostname; + } + + /** + * Get the anonymous ID for the SDK. + * This ID is used to track the user's activity across different sessions anonymously. + * @returns {Promise} - A promise that resolves to the anonymous ID. + */ + async getAnonId(): Promise { + if (this._anonId) { + return this._anonId; + } + + let anonId: string; + if (this.platformManager?.isBrowser()) { + anonId = await this.getBrowserAnonId(); + } else if (this.platformManager?.isReactNative()) { + anonId = await this.getReactNativeAnonId(); + } else { + anonId = uuidv4(); + } + + this._anonId = anonId; + return anonId; + } + + /** + * Retrieve or generate the anonymous ID for browser environments using localStorage. + * @returns {Promise} - A promise that resolves to the anonymous ID. + */ + private getBrowserAnonId(): Promise { + return Promise.resolve().then(() => { + const key = this.ANON_ID_STORAGE_KEY; + try { + const storedId = localStorage.getItem(key); + if (storedId) { + return storedId; + } + const newId = uuidv4(); + localStorage.setItem(key, newId); + return newId; + } catch (e) { + console.warn('LocalStorage access error:', e); + return uuidv4(); + } + }); + } + + /** + * Retrieve or generate the anonymous ID for React Native environments using AsyncStorage. + * @returns {Promise} - A promise that resolves to the anonymous ID. + */ + private async getReactNativeAnonId(): Promise { + const key = this.ANON_ID_STORAGE_KEY; + try { + const AsyncStorage = + // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports + require('@react-native-async-storage/async-storage').default; + const storedId = await AsyncStorage.getItem(key); + if (storedId) { + return storedId; + } + const newId = uuidv4(); + await AsyncStorage.setItem(key, newId); + return newId; + } catch (e) { + console.warn('Error accessing AsyncStorage:', e); + return uuidv4(); + } + } + getWalletStatus() { return this.remoteConnection?.getConnector()?.getConnectionStatus(); } diff --git a/packages/sdk/src/services/MetaMaskSDK/InitializerManager/performSDKInitialization.ts b/packages/sdk/src/services/MetaMaskSDK/InitializerManager/performSDKInitialization.ts index ba9add875..2e1e2ea84 100644 --- a/packages/sdk/src/services/MetaMaskSDK/InitializerManager/performSDKInitialization.ts +++ b/packages/sdk/src/services/MetaMaskSDK/InitializerManager/performSDKInitialization.ts @@ -7,6 +7,7 @@ import { logger } from '../../../utils/logger'; import { handleAutoAndExtensionConnections } from './handleAutoAndExtensionConnections'; import { initializeProviderAndEventListeners } from './initializeProviderAndEventListeners'; import { setupAnalytics } from './setupAnalytics'; +import { setupAnalyticsV2 } from './setupAnalyticsV2'; import { setupDappMetadata } from './setupDappMetadata'; import { setupExtensionPreferences } from './setupExtensionPreferences'; import { setupInfuraProvider } from './setupInfuraProvider'; @@ -100,6 +101,8 @@ export async function performSDKInitialization(instance: MetaMaskSDK) { await setupAnalytics(instance); + await setupAnalyticsV2(instance); + await setupStorageManager(instance); await setupDappMetadata(instance); diff --git a/packages/sdk/src/services/MetaMaskSDK/InitializerManager/setupAnalytics.ts b/packages/sdk/src/services/MetaMaskSDK/InitializerManager/setupAnalytics.ts index 8a92d2799..094c5ff0c 100644 --- a/packages/sdk/src/services/MetaMaskSDK/InitializerManager/setupAnalytics.ts +++ b/packages/sdk/src/services/MetaMaskSDK/InitializerManager/setupAnalytics.ts @@ -23,10 +23,7 @@ export async function setupAnalytics(instance: MetaMaskSDK) { originatorInfo: { url: options.dappMetadata.url ?? '', title: options.dappMetadata.name ?? '', - dappId: - typeof window === 'undefined' || typeof window.location === 'undefined' - ? options.dappMetadata?.name ?? options.dappMetadata?.url ?? 'N/A' - : window.location.hostname, + dappId: instance.getDappId(), platform: platformType ?? '', source: options._source ?? '', }, diff --git a/packages/sdk/src/services/MetaMaskSDK/InitializerManager/setupAnalyticsV2.ts b/packages/sdk/src/services/MetaMaskSDK/InitializerManager/setupAnalyticsV2.ts new file mode 100644 index 000000000..c95f8156d --- /dev/null +++ b/packages/sdk/src/services/MetaMaskSDK/InitializerManager/setupAnalyticsV2.ts @@ -0,0 +1,40 @@ +import { analytics } from '@metamask/sdk-analytics'; +import { MetaMaskSDK } from '../../../sdk'; + +/** + * Sets up the analytics instance for the MetaMask SDK. + * + * This function enables the global analytics client and sets the global properties. + * + * @param instance The MetaMaskSDK instance for which analytics will be set up. + * @returns void + * @async + */ +export async function setupAnalyticsV2(instance: MetaMaskSDK) { + if (!instance.options.enableAnalytics) { + return; + } + + if ( + !instance.platformManager?.isBrowser() && + !instance.platformManager?.isReactNative() + ) { + return; + } + + const version = instance.getVersion(); + const dappId = instance.getDappId(); + const anonId = await instance.getAnonId(); + const platform = instance.platformManager?.getPlatformType() as string; + const integrationType = instance.options._source as string; + + analytics.setGlobalProperty('sdk_version', version); + analytics.setGlobalProperty('dapp_id', dappId); + analytics.setGlobalProperty('anon_id', anonId); + analytics.setGlobalProperty('platform', platform); + analytics.setGlobalProperty('integration_type', integrationType); + + analytics.enable(); + + analytics.track('sdk_initialized', {}); +} diff --git a/packages/sdk/src/services/RemoteConnection/ConnectionManager/connectWithModalInstaller.ts b/packages/sdk/src/services/RemoteConnection/ConnectionManager/connectWithModalInstaller.ts index 1ed61c326..6e9cf840b 100644 --- a/packages/sdk/src/services/RemoteConnection/ConnectionManager/connectWithModalInstaller.ts +++ b/packages/sdk/src/services/RemoteConnection/ConnectionManager/connectWithModalInstaller.ts @@ -1,3 +1,4 @@ +import { analytics } from '@metamask/sdk-analytics'; import { EventType } from '@metamask/sdk-communication-layer'; import { logger } from '../../../utils/logger'; import { PROVIDER_UPDATE_TYPE } from '../../../types/ProviderUpdateType'; @@ -61,11 +62,19 @@ export async function connectWithModalInstaller( }, ); + const connectionTimeout = setTimeout(() => { + analytics.track('sdk_connection_failed', { + transport_type: 'websocket', + }); + }, 60_000); + state.connector.once(EventType.AUTHORIZED, () => { + clearTimeout(connectionTimeout); resolve(); }); state.connector.once(EventType.REJECTED, () => { + clearTimeout(connectionTimeout); reject(EventType.REJECTED); }); diff --git a/packages/sdk/src/services/RemoteConnection/ConnectionManager/startConnection.ts b/packages/sdk/src/services/RemoteConnection/ConnectionManager/startConnection.ts index 3324f3720..5fc3f08b9 100644 --- a/packages/sdk/src/services/RemoteConnection/ConnectionManager/startConnection.ts +++ b/packages/sdk/src/services/RemoteConnection/ConnectionManager/startConnection.ts @@ -1,3 +1,4 @@ +import { analytics } from '@metamask/sdk-analytics'; import { DEFAULT_SESSION_TIMEOUT_MS, EventType, @@ -57,6 +58,10 @@ export async function startConnection( // Establish socket connection provider.emit('connecting'); + analytics.track('sdk_connection_initiated', { + transport_type: 'websocket', + }); + const channelConfig = await state.connector?.originatorSessionConnect(); logger( `[RemoteConnection: startConnection()] after originatorSessionConnect initialCheck=${initialCheck}`, @@ -187,11 +192,19 @@ export async function startConnection( return; } + const connectionTimeout = setTimeout(() => { + analytics.track('sdk_connection_failed', { + transport_type: 'websocket', + }); + }, 60_000); + state.connector?.once(EventType.AUTHORIZED, () => { + clearTimeout(connectionTimeout); resolve(); }); state.connector?.once(EventType.REJECTED, () => { + clearTimeout(connectionTimeout); reject(EventType.REJECTED); }); }); diff --git a/packages/sdk/src/services/SDKProvider/ChainManager/handleChainChanged.ts b/packages/sdk/src/services/SDKProvider/ChainManager/handleChainChanged.ts index cf464b02e..ee8d30407 100644 --- a/packages/sdk/src/services/SDKProvider/ChainManager/handleChainChanged.ts +++ b/packages/sdk/src/services/SDKProvider/ChainManager/handleChainChanged.ts @@ -1,3 +1,4 @@ +import { analytics } from '@metamask/sdk-analytics'; import { logger } from '../../../utils/logger'; import { SDKProvider } from '../../../provider/SDKProvider'; @@ -36,6 +37,10 @@ export function handleChainChanged({ `[SDKProvider: handleChainChanged()] chainId=${chainId} networkVersion=${networkVersion}`, ); + analytics.track('sdk_used_chain', { + caip_chain_id: `eip155:${parseInt(chainId ?? '0x1', 16)}`, + }); + // FIXME on RN IOS networkVersion is sometime missing? why? let forcedNetworkVersion = networkVersion; if (!networkVersion) { diff --git a/yarn.lock b/yarn.lock index 5313f5cc2..9bbe45d9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6756,6 +6756,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/aix-ppc64@npm:0.25.3" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-arm64@npm:0.18.20" @@ -6770,6 +6777,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/android-arm64@npm:0.25.3" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-arm@npm:0.18.20" @@ -6784,6 +6798,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/android-arm@npm:0.25.3" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-x64@npm:0.18.20" @@ -6798,6 +6819,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/android-x64@npm:0.25.3" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/darwin-arm64@npm:0.18.20" @@ -6812,6 +6840,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/darwin-arm64@npm:0.25.3" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/darwin-x64@npm:0.18.20" @@ -6826,6 +6861,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/darwin-x64@npm:0.25.3" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/freebsd-arm64@npm:0.18.20" @@ -6840,6 +6882,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/freebsd-arm64@npm:0.25.3" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/freebsd-x64@npm:0.18.20" @@ -6854,6 +6903,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/freebsd-x64@npm:0.25.3" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-arm64@npm:0.18.20" @@ -6868,6 +6924,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-arm64@npm:0.25.3" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-arm@npm:0.18.20" @@ -6882,6 +6945,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-arm@npm:0.25.3" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-ia32@npm:0.18.20" @@ -6896,6 +6966,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-ia32@npm:0.25.3" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-loong64@npm:0.18.20" @@ -6910,6 +6987,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-loong64@npm:0.25.3" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-mips64el@npm:0.18.20" @@ -6924,6 +7008,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-mips64el@npm:0.25.3" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-ppc64@npm:0.18.20" @@ -6938,6 +7029,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-ppc64@npm:0.25.3" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-riscv64@npm:0.18.20" @@ -6952,6 +7050,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-riscv64@npm:0.25.3" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-s390x@npm:0.18.20" @@ -6966,6 +7071,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-s390x@npm:0.25.3" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/linux-x64@npm:0.18.20" @@ -6980,6 +7092,20 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/linux-x64@npm:0.25.3" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-arm64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/netbsd-arm64@npm:0.25.3" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/netbsd-x64@npm:0.18.20" @@ -6994,6 +7120,20 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/netbsd-x64@npm:0.25.3" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/openbsd-arm64@npm:0.25.3" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/openbsd-x64@npm:0.18.20" @@ -7008,6 +7148,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/openbsd-x64@npm:0.25.3" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/sunos-x64@npm:0.18.20" @@ -7022,6 +7169,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/sunos-x64@npm:0.25.3" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-arm64@npm:0.18.20" @@ -7036,6 +7190,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/win32-arm64@npm:0.25.3" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-ia32@npm:0.18.20" @@ -7050,6 +7211,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/win32-ia32@npm:0.25.3" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/win32-x64@npm:0.18.20" @@ -7064,6 +7232,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.25.3": + version: 0.25.3 + resolution: "@esbuild/win32-x64@npm:0.25.3" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -7121,6 +7296,24 @@ __metadata: languageName: node linkType: hard +"@eslint/config-array@npm:^0.20.0": + version: 0.20.0 + resolution: "@eslint/config-array@npm:0.20.0" + dependencies: + "@eslint/object-schema": ^2.1.6 + debug: ^4.3.1 + minimatch: ^3.1.2 + checksum: 55824ea31f0502166a6fea97176c9c25089a0354474cdc72a5f739b1cf6925f44f667bf8f4f3a9dabf1112ab0fa671778ca3f96f1499f31ec42caf84cae55005 + languageName: node + linkType: hard + +"@eslint/config-helpers@npm:^0.2.1": + version: 0.2.1 + resolution: "@eslint/config-helpers@npm:0.2.1" + checksum: b463805bc319608436a8b19c94fd533d8196b326c03361db54c0f3ec59d7bd6337c9764bc945ef15df94f50443973241dc265f661b07aceed4938f7d1cf2e822 + languageName: node + linkType: hard + "@eslint/core@npm:^0.10.0": version: 0.10.0 resolution: "@eslint/core@npm:0.10.0" @@ -7130,6 +7323,15 @@ __metadata: languageName: node linkType: hard +"@eslint/core@npm:^0.13.0": + version: 0.13.0 + resolution: "@eslint/core@npm:0.13.0" + dependencies: + "@types/json-schema": ^7.0.15 + checksum: 4d1a4163ba7f667297ba6e60de82f41d139b01951e2870b1bb609072c3c5df68b0288cc911ce3af0564dfa19bfda23cbf04eebd243ccb4960e0b5f927aa9a723 + languageName: node + linkType: hard + "@eslint/eslintrc@npm:^0.4.3": version: 0.4.3 resolution: "@eslint/eslintrc@npm:0.4.3" @@ -7232,6 +7434,23 @@ __metadata: languageName: node linkType: hard +"@eslint/eslintrc@npm:^3.3.1": + version: 3.3.1 + resolution: "@eslint/eslintrc@npm:3.3.1" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^10.0.1 + globals: ^14.0.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: 8241f998f0857abf5a615072273b90b1244d75c1c45d217c6a8eb444c6e12bbb5506b4879c14fb262eb72b7d8e3d2f0542da2db1a7f414a12496ebb790fb4d62 + languageName: node + linkType: hard + "@eslint/js@npm:8.44.0": version: 8.44.0 resolution: "@eslint/js@npm:8.44.0" @@ -7267,6 +7486,13 @@ __metadata: languageName: node linkType: hard +"@eslint/js@npm:9.25.1": + version: 9.25.1 + resolution: "@eslint/js@npm:9.25.1" + checksum: f5b9c9c40694fbb858fc84ac0f9468ca3f09d8b4935da21dcab3f65c094e8e266a4926ec7bb1e18441440c5ddd722a5f62dabd58096aefbe6b517ed809d8fa8b + languageName: node + linkType: hard + "@eslint/object-schema@npm:^2.1.5": version: 2.1.5 resolution: "@eslint/object-schema@npm:2.1.5" @@ -7274,6 +7500,13 @@ __metadata: languageName: node linkType: hard +"@eslint/object-schema@npm:^2.1.6": + version: 2.1.6 + resolution: "@eslint/object-schema@npm:2.1.6" + checksum: e32e565319f6544d36d3fa69a3e163120722d12d666d1a4525c9a6f02e9b54c29d9b1f03139e25d7e759e08dda8da433590bc23c09db8d511162157ef1b86a4c + languageName: node + linkType: hard + "@eslint/plugin-kit@npm:^0.2.5": version: 0.2.5 resolution: "@eslint/plugin-kit@npm:0.2.5" @@ -7284,6 +7517,16 @@ __metadata: languageName: node linkType: hard +"@eslint/plugin-kit@npm:^0.2.8": + version: 0.2.8 + resolution: "@eslint/plugin-kit@npm:0.2.8" + dependencies: + "@eslint/core": ^0.13.0 + levn: ^0.4.1 + checksum: b5bd769f3f96cb3bdc4051d9ebd973b30d1cd00a02953ded1eeb74fb5b2af73cf38c20cc76acddc8e74828f0dbf92ba9d725414b3026177935fc4b48784a7fba + languageName: node + linkType: hard + "@ethereumjs/common@npm:^3.2.0": version: 3.2.0 resolution: "@ethereumjs/common@npm:3.2.0" @@ -9279,6 +9522,13 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/retry@npm:^0.4.2": + version: 0.4.2 + resolution: "@humanwhocodes/retry@npm:0.4.2" + checksum: 764127449a9f97d807b9c47f898fce8d7e0e8e8438366116b9ddcaacded99b2c285b8eed2cfdd5fdcb68be47728218db949f9618a58c0d3898d9fd14a6d6671e + languageName: node + linkType: hard + "@img/sharp-darwin-arm64@npm:0.33.5": version: 0.33.5 resolution: "@img/sharp-darwin-arm64@npm:0.33.5" @@ -10511,6 +10761,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:0.3.9": version: 0.3.9 resolution: "@jridgewell/trace-mapping@npm:0.3.9" @@ -11167,6 +11424,20 @@ __metadata: languageName: node linkType: hard +"@metamask/sdk-analytics@workspace:*, @metamask/sdk-analytics@workspace:packages/sdk-analytics": + version: 0.0.0-use.local + resolution: "@metamask/sdk-analytics@workspace:packages/sdk-analytics" + dependencies: + "@typescript-eslint/eslint-plugin": ^8.31.0 + "@typescript-eslint/parser": ^8.31.0 + eslint: ^9.25.1 + nock: ^14.0.4 + openapi-fetch: ^0.13.5 + typescript: ^5.8.3 + vitest: ^3.1.2 + languageName: unknown + linkType: soft + "@metamask/sdk-communication-layer@npm:0.11.1": version: 0.11.1 resolution: "@metamask/sdk-communication-layer@npm:0.11.1" @@ -11210,6 +11481,7 @@ __metadata: "@metamask/eslint-config": ^6.0.0 "@metamask/eslint-config-nodejs": ^6.0.0 "@metamask/eslint-config-typescript": ^6.0.0 + "@metamask/sdk-analytics": "workspace:*" "@rollup/plugin-commonjs": ^25.0.0 "@rollup/plugin-json": ^6.0.0 "@rollup/plugin-node-resolve": ^15.0.2 @@ -11844,6 +12116,7 @@ __metadata: "@metamask/eslint-config-typescript": ^6.0.0 "@metamask/onboarding": ^1.0.1 "@metamask/providers": 16.1.0 + "@metamask/sdk-analytics": "workspace:*" "@metamask/sdk-communication-layer": "workspace:*" "@metamask/sdk-install-modal-web": "workspace:*" "@paulmillr/qr": ^0.2.1 @@ -12068,6 +12341,20 @@ __metadata: languageName: node linkType: hard +"@mswjs/interceptors@npm:^0.38.5": + version: 0.38.6 + resolution: "@mswjs/interceptors@npm:0.38.6" + dependencies: + "@open-draft/deferred-promise": ^2.2.0 + "@open-draft/logger": ^0.3.0 + "@open-draft/until": ^2.0.0 + is-node-process: ^1.2.0 + outvariant: ^1.4.3 + strict-event-emitter: ^0.5.1 + checksum: 6b16b2ecb28fce2a9b04718231a8e6f3a9d1ca30eac6f5091c04b5c891b8bbc1a2bb69e6777bd96a680b1e51e2f88a9738056471312fac7ccd82e4038c85f2e8 + languageName: node + linkType: hard + "@napi-rs/snappy-android-arm-eabi@npm:7.2.2": version: 7.2.2 resolution: "@napi-rs/snappy-android-arm-eabi@npm:7.2.2" @@ -12609,6 +12896,30 @@ __metadata: languageName: node linkType: hard +"@open-draft/deferred-promise@npm:^2.2.0": + version: 2.2.0 + resolution: "@open-draft/deferred-promise@npm:2.2.0" + checksum: 7f29d39725bb8ab5b62f89d88a4202ce2439ac740860979f9e3d0015dfe4bc3daddcfa5727fa4eed482fdbee770aa591b1136b98b0a0f0569a65294f35bdf56a + languageName: node + linkType: hard + +"@open-draft/logger@npm:^0.3.0": + version: 0.3.0 + resolution: "@open-draft/logger@npm:0.3.0" + dependencies: + is-node-process: ^1.2.0 + outvariant: ^1.4.0 + checksum: 7adfe3d0ed8ca32333ce2a77f9a93d561ebc89c989eaa9722f1dc8a2d2854f5de1bef6fa6894cdf58e16fa4dd9cfa99444ea1f5cac6eb1518e9247911ed042d5 + languageName: node + linkType: hard + +"@open-draft/until@npm:^2.0.0": + version: 2.1.0 + resolution: "@open-draft/until@npm:2.1.0" + checksum: 140ea3b16f4a3a6a729c1256050e20a93d408d7aa1e125648ce2665b3c526ed452510c6e4a6f4b15d95fb5e41203fb51510eb8fbc8812d5e5a91880293d66471 + languageName: node + linkType: hard + "@opentelemetry/api@npm:^1.4.0": version: 1.9.0 resolution: "@opentelemetry/api@npm:1.9.0" @@ -15602,6 +15913,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.40.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-android-arm-eabi@npm:4.5.0" @@ -15616,6 +15934,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-android-arm64@npm:4.40.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-android-arm64@npm:4.5.0" @@ -15630,6 +15955,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.40.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-darwin-arm64@npm:4.5.0" @@ -15644,6 +15976,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.40.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-darwin-x64@npm:4.5.0" @@ -15658,6 +15997,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-arm64@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.40.0" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-x64@npm:4.26.0": version: 4.26.0 resolution: "@rollup/rollup-freebsd-x64@npm:4.26.0" @@ -15665,6 +16011,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-x64@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-freebsd-x64@npm:4.40.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.26.0": version: 4.26.0 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.26.0" @@ -15672,6 +16025,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.40.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.5.0" @@ -15686,6 +16046,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.40.0" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.26.0": version: 4.26.0 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.26.0" @@ -15693,6 +16060,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-gnu@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.40.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.5.0" @@ -15707,6 +16081,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.40.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.5.0" @@ -15714,6 +16095,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-loongarch64-gnu@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.40.0" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-powerpc64le-gnu@npm:4.26.0": version: 4.26.0 resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.26.0" @@ -15721,6 +16109,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.40.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.26.0": version: 4.26.0 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.26.0" @@ -15728,6 +16123,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.40.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-musl@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.40.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.26.0": version: 4.26.0 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.26.0" @@ -15735,6 +16144,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.40.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.26.0": version: 4.26.0 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.26.0" @@ -15742,6 +16158,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.40.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.5.0" @@ -15756,6 +16179,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.40.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-linux-x64-musl@npm:4.5.0" @@ -15770,6 +16200,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.40.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.5.0" @@ -15784,6 +16221,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.40.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.5.0" @@ -15798,6 +16242,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.40.0": + version: 4.40.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.40.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.5.0": version: 4.5.0 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.5.0" @@ -19007,6 +19458,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:1.0.7": + version: 1.0.7 + resolution: "@types/estree@npm:1.0.7" + checksum: d9312b7075bdd08f3c9e1bb477102f5458aaa42a8eec31a169481ce314ca99ac716645cff4fca81ea65a2294b0276a0de63159d1baca0f8e7b5050a92de950ad + languageName: node + linkType: hard + "@types/estree@npm:^0.0.51": version: 0.0.51 resolution: "@types/estree@npm:0.0.51" @@ -20227,6 +20685,27 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:^8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.31.0" + dependencies: + "@eslint-community/regexpp": ^4.10.0 + "@typescript-eslint/scope-manager": 8.31.0 + "@typescript-eslint/type-utils": 8.31.0 + "@typescript-eslint/utils": 8.31.0 + "@typescript-eslint/visitor-keys": 8.31.0 + graphemer: ^1.4.0 + ignore: ^5.3.1 + natural-compare: ^1.4.0 + ts-api-utils: ^2.0.1 + peerDependencies: + "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <5.9.0" + checksum: aaaf8664ef83621f9a9fde3efb15f0422d1645d74ff79a6814df6520cdbdb8feee051f58f024f141d7b61a58259f18dd292b6369116cf6957ddc7377bbaea2e1 + languageName: node + linkType: hard + "@typescript-eslint/experimental-utils@npm:4.33.0, @typescript-eslint/experimental-utils@npm:^4.0.1": version: 4.33.0 resolution: "@typescript-eslint/experimental-utils@npm:4.33.0" @@ -20376,6 +20855,22 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:^8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/parser@npm:8.31.0" + dependencies: + "@typescript-eslint/scope-manager": 8.31.0 + "@typescript-eslint/types": 8.31.0 + "@typescript-eslint/typescript-estree": 8.31.0 + "@typescript-eslint/visitor-keys": 8.31.0 + debug: ^4.3.4 + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <5.9.0" + checksum: 7d35be4a51f4062b106b61591d4848feeceb6ec7c375c0f9d71780cf949d2d1a542ad5b893ca23333dcff73126ed9c05fd615fcc9652d4f78eb4d3922a47bd6b + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:4.33.0": version: 4.33.0 resolution: "@typescript-eslint/scope-manager@npm:4.33.0" @@ -20446,6 +20941,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/scope-manager@npm:8.31.0" + dependencies: + "@typescript-eslint/types": 8.31.0 + "@typescript-eslint/visitor-keys": 8.31.0 + checksum: df114f39eacfac6f38551aed3947cb01479f13ce182b7ed503eb8ea0e0cfac15b9b5a35c01c33f83eb162009169895a551a1b63133988f809f55d212f76bd2bc + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/type-utils@npm:5.62.0" @@ -20529,6 +21034,21 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/type-utils@npm:8.31.0" + dependencies: + "@typescript-eslint/typescript-estree": 8.31.0 + "@typescript-eslint/utils": 8.31.0 + debug: ^4.3.4 + ts-api-utils: ^2.0.1 + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <5.9.0" + checksum: 7932188fdf68e631dc0308f918950928a9cea19a9f91cb0b32b294e7ccc33ed9b265b6b353957d2bd721f79238e62135818ace8490b619e3890a1ba85bcaa3f6 + languageName: node + linkType: hard + "@typescript-eslint/types@npm:4.33.0": version: 4.33.0 resolution: "@typescript-eslint/types@npm:4.33.0" @@ -20578,6 +21098,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/types@npm:8.31.0" + checksum: 5c0cb0f421dca169efccacd25c1eff529446eceb337ed8a439b4d0e3f4c797658a6b34a5cc6b4436262c841e3719b01ac3d26766958757487f75f97c6e6dd1e3 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:4.33.0": version: 4.33.0 resolution: "@typescript-eslint/typescript-estree@npm:4.33.0" @@ -20705,6 +21232,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.31.0" + dependencies: + "@typescript-eslint/types": 8.31.0 + "@typescript-eslint/visitor-keys": 8.31.0 + debug: ^4.3.4 + fast-glob: ^3.3.2 + is-glob: ^4.0.3 + minimatch: ^9.0.4 + semver: ^7.6.0 + ts-api-utils: ^2.0.1 + peerDependencies: + typescript: ">=4.8.4 <5.9.0" + checksum: 1982056fa3b9aa3488408760cd15a41fd301444c998b2063c8e323aa9a715bf1cc36388c29a58f19c529de80578a738b4074e6d9da7eb8ed9c0eb4df7293f86d + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.45.0, @typescript-eslint/utils@npm:^5.58.0": version: 5.62.0 resolution: "@typescript-eslint/utils@npm:5.62.0" @@ -20786,6 +21331,21 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/utils@npm:8.31.0" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@typescript-eslint/scope-manager": 8.31.0 + "@typescript-eslint/types": 8.31.0 + "@typescript-eslint/typescript-estree": 8.31.0 + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <5.9.0" + checksum: 5569dbd4bc083bab18244e1e59119f0a55466460b1d1c659439c67bcab5fba97b84da4652798a132457a847bad7f1e76403d3c7905c49d8ebdb189f593dd1378 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:4.33.0": version: 4.33.0 resolution: "@typescript-eslint/visitor-keys@npm:4.33.0" @@ -20856,6 +21416,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.31.0": + version: 8.31.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.31.0" + dependencies: + "@typescript-eslint/types": 8.31.0 + eslint-visitor-keys: ^4.2.0 + checksum: ce88b8edb75517d4a4e9d262d7b60b5d5a1ead7cac181345a1df0dcb4c7da650785df226d2ce8abbdbd9dbf2b29040d026f792df59d3d0189236c334de56a06e + languageName: node + linkType: hard + "@ungap/structured-clone@npm:^1.2.0": version: 1.2.0 resolution: "@ungap/structured-clone@npm:1.2.0" @@ -20897,6 +21467,87 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:3.1.2": + version: 3.1.2 + resolution: "@vitest/expect@npm:3.1.2" + dependencies: + "@vitest/spy": 3.1.2 + "@vitest/utils": 3.1.2 + chai: ^5.2.0 + tinyrainbow: ^2.0.0 + checksum: 132d65f4495afc4a6e714328f2a3375e72a737444967039c50a569626aaef730af920145e10a4b188699a051ba76dcdf404ddbea12cded3e3206d7e516d6ddb9 + languageName: node + linkType: hard + +"@vitest/mocker@npm:3.1.2": + version: 3.1.2 + resolution: "@vitest/mocker@npm:3.1.2" + dependencies: + "@vitest/spy": 3.1.2 + estree-walker: ^3.0.3 + magic-string: ^0.30.17 + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 5d852acdaccc832759ce88801736f938a37eb9cb84c703b96563c45f41372a0120a0fb069dd63390fa779aeca46eb0f16a4786c3c41741603e3af49b738b3194 + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:3.1.2, @vitest/pretty-format@npm:^3.1.2": + version: 3.1.2 + resolution: "@vitest/pretty-format@npm:3.1.2" + dependencies: + tinyrainbow: ^2.0.0 + checksum: b218576f9226ec9b99720579e1b8fa5838bec47d84cfb76ccb8bedf42f8820ea3657934b2cfeb5ab41dcc89b0991d9b608318033a4f6ed511a38901a1132a26c + languageName: node + linkType: hard + +"@vitest/runner@npm:3.1.2": + version: 3.1.2 + resolution: "@vitest/runner@npm:3.1.2" + dependencies: + "@vitest/utils": 3.1.2 + pathe: ^2.0.3 + checksum: 219e1bc2ae7f38be0661b6520c24655a5739f4a6d3f88c992593f5a9419da184d5663af4907fcfa122a9c5e86bad58b5cb63f6857bb62af7655169fa90a4006b + languageName: node + linkType: hard + +"@vitest/snapshot@npm:3.1.2": + version: 3.1.2 + resolution: "@vitest/snapshot@npm:3.1.2" + dependencies: + "@vitest/pretty-format": 3.1.2 + magic-string: ^0.30.17 + pathe: ^2.0.3 + checksum: 014d3beb5603531801e8a2768f755b9358d403291bdff573dffa6999b93455232a9fdd7d311875eff5eb2e8fb9fbcd4d7fe470aa10ebd1c161db66b1369bbe9a + languageName: node + linkType: hard + +"@vitest/spy@npm:3.1.2": + version: 3.1.2 + resolution: "@vitest/spy@npm:3.1.2" + dependencies: + tinyspy: ^3.0.2 + checksum: afffa703173224aae1d0382b4ec6e6861882a8d8836d39761f19eeb7645a84a0ebdf31afaed3cf409b4c505803398b7bea84b536b20d27cd20592563c437c8db + languageName: node + linkType: hard + +"@vitest/utils@npm:3.1.2": + version: 3.1.2 + resolution: "@vitest/utils@npm:3.1.2" + dependencies: + "@vitest/pretty-format": 3.1.2 + loupe: ^3.1.3 + tinyrainbow: ^2.0.0 + checksum: 045660ca4642c57bcfbd0de28225f768b14ad288a75823165657b50283f9a858fdba06ca9789c116d44860ea6119ae8a3bb19a0b2343337f4a246bf6f0c7de01 + languageName: node + linkType: hard + "@wagmi/chains@npm:1.6.0": version: 1.6.0 resolution: "@wagmi/chains@npm:1.6.0" @@ -23170,6 +23821,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 + languageName: node + linkType: hard + "ast-types-flow@npm:^0.0.7": version: 0.0.7 resolution: "ast-types-flow@npm:0.0.7" @@ -24876,6 +25534,13 @@ __metadata: languageName: node linkType: hard +"cac@npm:^6.7.14": + version: 6.7.14 + resolution: "cac@npm:6.7.14" + checksum: 45a2496a9443abbe7f52a49b22fbe51b1905eff46e03fd5e6c98e3f85077be3f8949685a1849b1a9cd2bc3e5567dfebcf64f01ce01847baf918f1b37c839791a + languageName: node + linkType: hard + "cacache@npm:^15.3.0": version: 15.3.0 resolution: "cacache@npm:15.3.0" @@ -25174,6 +25839,19 @@ __metadata: languageName: node linkType: hard +"chai@npm:^5.2.0": + version: 5.2.0 + resolution: "chai@npm:5.2.0" + dependencies: + assertion-error: ^2.0.1 + check-error: ^2.1.1 + deep-eql: ^5.0.1 + loupe: ^3.1.0 + pathval: ^2.0.0 + checksum: 15e4ba12d02df3620fd59b4a6e8efe43b47872ce61f1c0ca77ac1205a2a5898f3b6f1f52408fd1a708b8d07fdfb5e65b97af40bad9fd94a69ed8d4264c7a69f1 + languageName: node + linkType: hard + "chalk-template@npm:0.4.0": version: 0.4.0 resolution: "chalk-template@npm:0.4.0" @@ -25256,6 +25934,13 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^2.1.1": + version: 2.1.1 + resolution: "check-error@npm:2.1.1" + checksum: d785ed17b1d4a4796b6e75c765a9a290098cf52ff9728ce0756e8ffd4293d2e419dd30c67200aee34202463b474306913f2fcfaf1890641026d9fc6966fea27a + languageName: node + linkType: hard + "check-types@npm:^11.1.1": version: 11.2.2 resolution: "check-types@npm:11.2.2" @@ -27089,6 +27774,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.4.0": + version: 4.4.0 + resolution: "debug@npm:4.4.0" + dependencies: + ms: ^2.1.3 + peerDependenciesMeta: + supports-color: + optional: true + checksum: fb42df878dd0e22816fc56e1fdca9da73caa85212fbe40c868b1295a6878f9101ae684f4eeef516c13acfc700f5ea07f1136954f43d4cd2d477a811144136479 + languageName: node + linkType: hard + "decamelize-keys@npm:^1.1.0": version: 1.1.1 resolution: "decamelize-keys@npm:1.1.1" @@ -27139,6 +27836,13 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^5.0.1": + version: 5.0.2 + resolution: "deep-eql@npm:5.0.2" + checksum: 6aaaadb4c19cbce42e26b2bbe5bd92875f599d2602635dc97f0294bae48da79e89470aedee05f449e0ca8c65e9fd7e7872624d1933a1db02713d99c2ca8d1f24 + languageName: node + linkType: hard + "deep-equal@npm:^2.0.5": version: 2.2.2 resolution: "deep-equal@npm:2.2.2" @@ -29046,6 +29750,13 @@ __metadata: languageName: node linkType: hard +"es-module-lexer@npm:^1.6.0": + version: 1.7.0 + resolution: "es-module-lexer@npm:1.7.0" + checksum: 7858bb76ae387fdbf8a6fccc951bf18919768309850587553eca34698b9193fbc65fab03d3d9f69163d860321fbf66adf89d5821e7f4148c7cb7d7b997259211 + languageName: node + linkType: hard + "es-object-atoms@npm:^1.0.0": version: 1.0.0 resolution: "es-object-atoms@npm:1.0.0" @@ -29375,6 +30086,92 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.25.0": + version: 0.25.3 + resolution: "esbuild@npm:0.25.3" + dependencies: + "@esbuild/aix-ppc64": 0.25.3 + "@esbuild/android-arm": 0.25.3 + "@esbuild/android-arm64": 0.25.3 + "@esbuild/android-x64": 0.25.3 + "@esbuild/darwin-arm64": 0.25.3 + "@esbuild/darwin-x64": 0.25.3 + "@esbuild/freebsd-arm64": 0.25.3 + "@esbuild/freebsd-x64": 0.25.3 + "@esbuild/linux-arm": 0.25.3 + "@esbuild/linux-arm64": 0.25.3 + "@esbuild/linux-ia32": 0.25.3 + "@esbuild/linux-loong64": 0.25.3 + "@esbuild/linux-mips64el": 0.25.3 + "@esbuild/linux-ppc64": 0.25.3 + "@esbuild/linux-riscv64": 0.25.3 + "@esbuild/linux-s390x": 0.25.3 + "@esbuild/linux-x64": 0.25.3 + "@esbuild/netbsd-arm64": 0.25.3 + "@esbuild/netbsd-x64": 0.25.3 + "@esbuild/openbsd-arm64": 0.25.3 + "@esbuild/openbsd-x64": 0.25.3 + "@esbuild/sunos-x64": 0.25.3 + "@esbuild/win32-arm64": 0.25.3 + "@esbuild/win32-ia32": 0.25.3 + "@esbuild/win32-x64": 0.25.3 + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 1f9af51aa1d7d1f57e7294823d19ed69b0f6da413b7b0e8123abcebd1bb4011ef19961e2e6679c07301fcd00a85c4d102160fc40a91c25ceeaf594932509d84d + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -30300,6 +31097,16 @@ __metadata: languageName: node linkType: hard +"eslint-scope@npm:^8.3.0": + version: 8.3.0 + resolution: "eslint-scope@npm:8.3.0" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^5.2.0 + checksum: 57a58b6716533e25d527089826c4add89a047aecf75e4a88fee05f113ef5a72b85392b304a69bf670646cc3e068354aec70361b9718c2453949a05fc4d9bfe73 + languageName: node + linkType: hard + "eslint-utils@npm:^2.0.0, eslint-utils@npm:^2.1.0": version: 2.1.0 resolution: "eslint-utils@npm:2.1.0" @@ -30660,6 +31467,56 @@ __metadata: languageName: node linkType: hard +"eslint@npm:^9.25.1": + version: 9.25.1 + resolution: "eslint@npm:9.25.1" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.12.1 + "@eslint/config-array": ^0.20.0 + "@eslint/config-helpers": ^0.2.1 + "@eslint/core": ^0.13.0 + "@eslint/eslintrc": ^3.3.1 + "@eslint/js": 9.25.1 + "@eslint/plugin-kit": ^0.2.8 + "@humanfs/node": ^0.16.6 + "@humanwhocodes/module-importer": ^1.0.1 + "@humanwhocodes/retry": ^0.4.2 + "@types/estree": ^1.0.6 + "@types/json-schema": ^7.0.15 + ajv: ^6.12.4 + chalk: ^4.0.0 + cross-spawn: ^7.0.6 + debug: ^4.3.2 + escape-string-regexp: ^4.0.0 + eslint-scope: ^8.3.0 + eslint-visitor-keys: ^4.2.0 + espree: ^10.3.0 + esquery: ^1.5.0 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^8.0.0 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + json-stable-stringify-without-jsonify: ^1.0.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + peerDependencies: + jiti: "*" + peerDependenciesMeta: + jiti: + optional: true + bin: + eslint: bin/eslint.js + checksum: 498a9dcb28f7ad154e5ad744a80f31397fe971959c317af710794de3cc3518e59f581d0a1668b9d3872f05dbff55093c23019677a729087d097c19295473eb8b + languageName: node + linkType: hard + "espree@npm:^10.0.1, espree@npm:^10.3.0": version: 10.3.0 resolution: "espree@npm:10.3.0" @@ -30796,6 +31653,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": ^1.0.0 + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -31237,6 +32103,13 @@ __metadata: languageName: node linkType: hard +"expect-type@npm:^1.2.1": + version: 1.2.1 + resolution: "expect-type@npm:1.2.1" + checksum: 4fc41ff0c784cb8984ab7801326251d3178083661f0ad08bbd3e5ca789293e6b66d5082f0cef83ebf9849c85d0280a19df5e4e2c57999a2464db9a01c7e3344f + languageName: node + linkType: hard + "expect@npm:^27.5.1": version: 27.5.1 resolution: "expect@npm:27.5.1" @@ -32027,6 +32900,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.4.4": + version: 6.4.4 + resolution: "fdir@npm:6.4.4" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 79043610236579ffbd0647c508b43bd030a2d034a17c43cf96813a00e8e92e51acdb115c6ddecef3b5812cc2692b976155b4f6413e51e3761f1e772fa019a321 + languageName: node + linkType: hard + "fecha@npm:^4.2.0": version: 4.2.3 resolution: "fecha@npm:4.2.3" @@ -32691,6 +33576,16 @@ __metadata: languageName: node linkType: hard +"fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + "fsevents@patch:fsevents@^2.3.2#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.2 resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" @@ -32700,6 +33595,15 @@ __metadata: languageName: node linkType: hard +"fsevents@patch:fsevents@~2.3.3#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + "function-bind@npm:^1.1.1": version: 1.1.1 resolution: "function-bind@npm:1.1.1" @@ -35006,6 +35910,13 @@ __metadata: languageName: node linkType: hard +"is-node-process@npm:^1.2.0": + version: 1.2.0 + resolution: "is-node-process@npm:1.2.0" + checksum: 930765cdc6d81ab8f1bbecbea4a8d35c7c6d88a3ff61f3630e0fc7f22d624d7661c1df05c58547d0eb6a639dfa9304682c8e342c4113a6ed51472b704cee2928 + languageName: node + linkType: hard + "is-number-object@npm:^1.0.4": version: 1.0.7 resolution: "is-number-object@npm:1.0.7" @@ -38983,6 +39894,13 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^3.1.0, loupe@npm:^3.1.3": + version: 3.1.3 + resolution: "loupe@npm:3.1.3" + checksum: 9b2530b1d5a44d2c9fc5241f97ea00296dca257173c535b4832bc31f9516e10387991feb5b3fff23df116c8fcf907ce3980f82b215dcc5d19cde17ce9b9ec3e1 + languageName: node + linkType: hard + "lower-case@npm:^2.0.2": version: 2.0.2 resolution: "lower-case@npm:2.0.2" @@ -39099,6 +40017,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.17": + version: 0.30.17 + resolution: "magic-string@npm:0.30.17" + dependencies: + "@jridgewell/sourcemap-codec": ^1.5.0 + checksum: f4b4ed17c5ada64f77fc98491847302ebad64894a905c417c943840c0384662118c9b37f9f68bb86add159fa4749ff6f118c4627d69a470121b46731f8debc6d + languageName: node + linkType: hard + "magic-string@npm:^0.30.3": version: 0.30.5 resolution: "magic-string@npm:0.30.5" @@ -41170,6 +42097,15 @@ __metadata: languageName: node linkType: hard +"nanoid@npm:^3.3.8": + version: 3.3.11 + resolution: "nanoid@npm:3.3.11" + bin: + nanoid: bin/nanoid.cjs + checksum: 3be20d8866a57a6b6d218e82549711c8352ed969f9ab3c45379da28f405363ad4c9aeb0b39e9abc101a529ca65a72ff9502b00bf74a912c4b64a9d62dfd26c29 + languageName: node + linkType: hard + "nanoid@npm:^4.0.0": version: 4.0.2 resolution: "nanoid@npm:4.0.2" @@ -41496,6 +42432,17 @@ __metadata: languageName: node linkType: hard +"nock@npm:^14.0.4": + version: 14.0.4 + resolution: "nock@npm:14.0.4" + dependencies: + "@mswjs/interceptors": ^0.38.5 + json-stringify-safe: ^5.0.1 + propagate: ^2.0.0 + checksum: 60425c4b7a706775459479bef488c770ce93bc982cbdb5ea88473cdd4612f40633221bd678c9224d59b0efbfbcda39c282c52f756dbebbe5d5219e8415cd97ff + languageName: node + linkType: hard + "node-abort-controller@npm:^3.0.1, node-abort-controller@npm:^3.1.1": version: 3.1.1 resolution: "node-abort-controller@npm:3.1.1" @@ -42387,6 +43334,22 @@ __metadata: languageName: node linkType: hard +"openapi-fetch@npm:^0.13.5": + version: 0.13.5 + resolution: "openapi-fetch@npm:0.13.5" + dependencies: + openapi-typescript-helpers: ^0.0.15 + checksum: 7f6947d074d3a66fbc1641e46b20652cc92412e6b3238259a29ad72ef6eca5b4ac7529826ff97660fc6ebc8c38f2f151ad66e9e93f16b0736bec5c150f73b06f + languageName: node + linkType: hard + +"openapi-typescript-helpers@npm:^0.0.15": + version: 0.0.15 + resolution: "openapi-typescript-helpers@npm:0.0.15" + checksum: feec0f25d708aaacc086dafd3e21001329b47984f30e24877b34d053fbccd52f3b3a19b1715fda2ed5afaca7056872576eed7de8f64855d2472507dc6df626ca + languageName: node + linkType: hard + "opener@npm:1": version: 1.5.2 resolution: "opener@npm:1.5.2" @@ -42472,6 +43435,13 @@ __metadata: languageName: node linkType: hard +"outvariant@npm:^1.4.0, outvariant@npm:^1.4.3": + version: 1.4.3 + resolution: "outvariant@npm:1.4.3" + checksum: 4a3551fb2b45309e585eebf88bad094dbe56ac6d3a28d59dd2e4050b431aa2beb6097a0763fce3cd82ca0f077026f380a9b60fffc306aaf430141421e7a7b6ed + languageName: node + linkType: hard + "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -42939,6 +43909,20 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^2.0.3": + version: 2.0.3 + resolution: "pathe@npm:2.0.3" + checksum: 0602bdd4acb54d91044e0c56f1fb63467ae7d44ab3afea1f797947b0eb2b4d1d91cf0d58d065fdb0a8ab0c4acbbd8d3a5b424983eaf10dd5285d37a16f6e3ee9 + languageName: node + linkType: hard + +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: 682b6a6289de7990909effef7dae9aa7bb6218c0426727bccf66a35b34e7bfbc65615270c5e44e3c9557a5cb44b1b9ef47fc3cb18bce6ad3ba92bcd28467ed7d + languageName: node + linkType: hard + "pbkdf2@npm:3.0.8": version: 3.0.8 resolution: "pbkdf2@npm:3.0.8" @@ -43014,7 +43998,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.1.0": +"picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -44186,6 +45170,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.5.3": + version: 8.5.3 + resolution: "postcss@npm:8.5.3" + dependencies: + nanoid: ^3.3.8 + picocolors: ^1.1.1 + source-map-js: ^1.2.1 + checksum: da574620eb84ff60e65e1d8fc6bd5ad87a19101a23d0aba113c653434161543918229a0f673d89efb3b6d4906287eb04b957310dbcf4cbebacad9d1312711461 + languageName: node + linkType: hard + "postcss@npm:~8.4.32": version: 8.4.38 resolution: "postcss@npm:8.4.38" @@ -44488,6 +45483,13 @@ __metadata: languageName: node linkType: hard +"propagate@npm:^2.0.0": + version: 2.0.1 + resolution: "propagate@npm:2.0.1" + checksum: c4febaee2be0979e82fb6b3727878fd122a98d64a7fa3c9d09b0576751b88514a9e9275b1b92e76b364d488f508e223bd7e1dcdc616be4cdda876072fbc2a96c + languageName: node + linkType: hard + "protobufjs@npm:^7.2.4": version: 7.2.5 resolution: "protobufjs@npm:7.2.5" @@ -47424,6 +48426,81 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.34.9": + version: 4.40.0 + resolution: "rollup@npm:4.40.0" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.40.0 + "@rollup/rollup-android-arm64": 4.40.0 + "@rollup/rollup-darwin-arm64": 4.40.0 + "@rollup/rollup-darwin-x64": 4.40.0 + "@rollup/rollup-freebsd-arm64": 4.40.0 + "@rollup/rollup-freebsd-x64": 4.40.0 + "@rollup/rollup-linux-arm-gnueabihf": 4.40.0 + "@rollup/rollup-linux-arm-musleabihf": 4.40.0 + "@rollup/rollup-linux-arm64-gnu": 4.40.0 + "@rollup/rollup-linux-arm64-musl": 4.40.0 + "@rollup/rollup-linux-loongarch64-gnu": 4.40.0 + "@rollup/rollup-linux-powerpc64le-gnu": 4.40.0 + "@rollup/rollup-linux-riscv64-gnu": 4.40.0 + "@rollup/rollup-linux-riscv64-musl": 4.40.0 + "@rollup/rollup-linux-s390x-gnu": 4.40.0 + "@rollup/rollup-linux-x64-gnu": 4.40.0 + "@rollup/rollup-linux-x64-musl": 4.40.0 + "@rollup/rollup-win32-arm64-msvc": 4.40.0 + "@rollup/rollup-win32-ia32-msvc": 4.40.0 + "@rollup/rollup-win32-x64-msvc": 4.40.0 + "@types/estree": 1.0.7 + fsevents: ~2.3.2 + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-loongarch64-gnu": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 4826d7bbb48147403023133b6d8a67f792efe3463def637713bed392b5d7fc9903b4b86de44c58420304beca9e8d108268036e9081fff675af6c01822ef6b2b9 + languageName: node + linkType: hard + "rollup@npm:^4.5.0": version: 4.5.0 resolution: "rollup@npm:4.5.0" @@ -48411,6 +49488,13 @@ __metadata: languageName: node linkType: hard +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 8aa5a98640ca09fe00d74416eca97551b3e42991614a3d1b824b115fc1401543650914f651ab1311518177e4d297e80b953f4cd4cd7ea1eabe824e8f2091de01 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -48828,6 +49912,13 @@ __metadata: languageName: node linkType: hard +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 4eb0cd997cdf228bc253bcaff9340afeb706176e64868ecd20efbe6efea931465f43955612346d6b7318789e5265bdc419bc7669c1cebe3db0eb255f57efa76b + languageName: node + linkType: hard + "source-map-loader@npm:^3.0.0": version: 3.0.2 resolution: "source-map-loader@npm:3.0.2" @@ -49069,6 +50160,13 @@ __metadata: languageName: node linkType: hard +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 + languageName: node + linkType: hard + "stackframe@npm:^1.3.4": version: 1.3.4 resolution: "stackframe@npm:1.3.4" @@ -49134,6 +50232,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.9.0": + version: 3.9.0 + resolution: "std-env@npm:3.9.0" + checksum: d40126e4a650f6e5456711e6c297420352a376ef99a9599e8224d2d8f2ff2b91a954f3264fcef888d94fce5c9ae14992c5569761c95556fc87248ce4602ed212 + languageName: node + linkType: hard + "stop-iteration-iterator@npm:^1.0.0": version: 1.0.0 resolution: "stop-iteration-iterator@npm:1.0.0" @@ -49282,6 +50387,13 @@ __metadata: languageName: node linkType: hard +"strict-event-emitter@npm:^0.5.1": + version: 0.5.1 + resolution: "strict-event-emitter@npm:0.5.1" + checksum: 350480431bc1c28fdb601ef4976c2f8155fc364b4740f9692dd03e5bdd48aafc99a5e021fe655fbd986d0b803e9f3fc5c4b018b35cb838c4690d60f2a26f1cf3 + languageName: node + linkType: hard + "strict-uri-encode@npm:^2.0.0": version: 2.0.0 resolution: "strict-uri-encode@npm:2.0.0" @@ -50667,6 +51779,30 @@ __metadata: languageName: node linkType: hard +"tinybench@npm:^2.9.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 1ab00d7dfe0d1f127cbf00822bacd9024f7a50a3ecd1f354a8168e0b7d2b53a639a24414e707c27879d1adc0f5153141d51d76ebd7b4d37fe245e742e5d91fe8 + languageName: node + linkType: hard + +"tinyexec@npm:^0.3.2": + version: 0.3.2 + resolution: "tinyexec@npm:0.3.2" + checksum: bd491923020610bdeadb0d8cf5d70e7cbad5a3201620fd01048c9bf3b31ffaa75c33254e1540e13b993ce4e8187852b0b5a93057bb598e7a57afa2ca2048a35c + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.13": + version: 0.2.13 + resolution: "tinyglobby@npm:0.2.13" + dependencies: + fdir: ^6.4.4 + picomatch: ^4.0.2 + checksum: 3a2e87a2518cb3616057b0aa58be4f17771ae78c6890556516ae1e631f8ce4cfee1ba1dcb62fcc54a64e2bdd6c3104f4f3d021e1a3e3f8fb0875bca380b913e5 + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.7": version: 0.2.10 resolution: "tinyglobby@npm:0.2.10" @@ -50677,6 +51813,27 @@ __metadata: languageName: node linkType: hard +"tinypool@npm:^1.0.2": + version: 1.0.2 + resolution: "tinypool@npm:1.0.2" + checksum: 752f23114d8fc95a9497fc812231d6d0a63728376aa11e6e8499c10423a91112e760e388887ea7854f1b16977c321f07c0eab061ec2f60f6761e58b184aac880 + languageName: node + linkType: hard + +"tinyrainbow@npm:^2.0.0": + version: 2.0.0 + resolution: "tinyrainbow@npm:2.0.0" + checksum: 26360631d97e43955a07cfb70fe40a154ce4e2bcd14fa3d37ce8e2ed8f4fa9e5ba00783e4906bbfefe6dcabef5d3510f5bee207cb693bee4e4e7553f5454bef1 + languageName: node + linkType: hard + +"tinyspy@npm:^3.0.2": + version: 3.0.2 + resolution: "tinyspy@npm:3.0.2" + checksum: 5db671b2ff5cd309de650c8c4761ca945459d7204afb1776db9a04fb4efa28a75f08517a8620c01ee32a577748802231ad92f7d5b194dc003ee7f987a2a06337 + languageName: node + linkType: hard + "titleize@npm:^3.0.0": version: 3.0.0 resolution: "titleize@npm:3.0.0" @@ -50874,6 +52031,15 @@ __metadata: languageName: node linkType: hard +"ts-api-utils@npm:^2.0.1": + version: 2.1.0 + resolution: "ts-api-utils@npm:2.1.0" + peerDependencies: + typescript: ">=4.8.4" + checksum: 5b1ef89105654d93d67582308bd8dfe4bbf6874fccbcaa729b08fbb00a940fd4c691ca6d0d2b18c3c70878d9a7e503421b7cc473dbc3d0d54258b86401d4b15d + languageName: node + linkType: hard + "ts-dedent@npm:^2.0.0, ts-dedent@npm:^2.2.0": version: 2.2.0 resolution: "ts-dedent@npm:2.2.0" @@ -51529,6 +52695,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.8.3": + version: 5.8.3 + resolution: "typescript@npm:5.8.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: cb1d081c889a288b962d3c8ae18d337ad6ee88a8e81ae0103fa1fecbe923737f3ba1dbdb3e6d8b776c72bc73bfa6d8d850c0306eed1a51377d2fccdfd75d92c4 + languageName: node + linkType: hard + "typescript@npm:~5.3.3": version: 5.3.3 resolution: "typescript@npm:5.3.3" @@ -51619,6 +52795,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@^5.8.3#~builtin": + version: 5.8.3 + resolution: "typescript@patch:typescript@npm%3A5.8.3#~builtin::version=5.8.3&hash=77c9e2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 1b503525a88ff0ff5952e95870971c4fb2118c17364d60302c21935dedcd6c37e6a0a692f350892bafcef6f4a16d09073fe461158547978d2f16fbe4cb18581c + languageName: node + linkType: hard + "typescript@patch:typescript@~5.3.3#~builtin": version: 5.3.3 resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=77c9e2" @@ -52530,6 +53716,130 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:3.1.2": + version: 3.1.2 + resolution: "vite-node@npm:3.1.2" + dependencies: + cac: ^6.7.14 + debug: ^4.4.0 + es-module-lexer: ^1.6.0 + pathe: ^2.0.3 + vite: ^5.0.0 || ^6.0.0 + bin: + vite-node: vite-node.mjs + checksum: eab025ba912af2805730cad3a89dc6801d3b0192ceecfb06cdb5e37dffd851263db9743c6e4192d69a75df0b7c19fb03b95272b18cac1f19201e06c09e6e8a1d + languageName: node + linkType: hard + +"vite@npm:^5.0.0 || ^6.0.0": + version: 6.3.3 + resolution: "vite@npm:6.3.3" + dependencies: + esbuild: ^0.25.0 + fdir: ^6.4.4 + fsevents: ~2.3.3 + picomatch: ^4.0.2 + postcss: ^8.5.3 + rollup: ^4.34.9 + tinyglobby: ^0.2.13 + peerDependencies: + "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: ">=1.21.0" + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: b12dcd715324d5033226005b514f281541578d619675724c6ba0f684efe875d145ae53404fc7dc604332f2b52b5bd197ed6b6edea219abd604336052f3f3c79e + languageName: node + linkType: hard + +"vitest@npm:^3.1.2": + version: 3.1.2 + resolution: "vitest@npm:3.1.2" + dependencies: + "@vitest/expect": 3.1.2 + "@vitest/mocker": 3.1.2 + "@vitest/pretty-format": ^3.1.2 + "@vitest/runner": 3.1.2 + "@vitest/snapshot": 3.1.2 + "@vitest/spy": 3.1.2 + "@vitest/utils": 3.1.2 + chai: ^5.2.0 + debug: ^4.4.0 + expect-type: ^1.2.1 + magic-string: ^0.30.17 + pathe: ^2.0.3 + std-env: ^3.9.0 + tinybench: ^2.9.0 + tinyexec: ^0.3.2 + tinyglobby: ^0.2.13 + tinypool: ^1.0.2 + tinyrainbow: ^2.0.0 + vite: ^5.0.0 || ^6.0.0 + vite-node: 3.1.2 + why-is-node-running: ^2.3.0 + peerDependencies: + "@edge-runtime/vm": "*" + "@types/debug": ^4.1.12 + "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 + "@vitest/browser": 3.1.2 + "@vitest/ui": 3.1.2 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/debug": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 67bef7675aa0c9e1554e497a60e016fa36a74ce758da126991974cc23c892266090d8a55cb89d92a065818d646218826e2f394ebd0361361fa574b6998fda6d6 + languageName: node + linkType: hard + "vlq@npm:^0.2.1, vlq@npm:^0.2.2": version: 0.2.3 resolution: "vlq@npm:0.2.3" @@ -53662,6 +54972,18 @@ __metadata: languageName: node linkType: hard +"why-is-node-running@npm:^2.3.0": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: ^2.0.0 + stackback: 0.0.2 + bin: + why-is-node-running: cli.js + checksum: 58ebbf406e243ace97083027f0df7ff4c2108baf2595bb29317718ef207cc7a8104e41b711ff65d6fa354f25daa8756b67f2f04931a4fd6ba9d13ae8197496fb + languageName: node + linkType: hard + "wide-align@npm:^1.1.5": version: 1.1.5 resolution: "wide-align@npm:1.1.5"